/*
    The portal's stylesheet.

    ==============================================================================================
    The token block below is the HCI York design system's tokens.json, light and dark, carried over
    exactly - the same block HCI Dialer's console holds. Do not edit a value here to change the look:
    change the design system, then copy the block across. Nothing else in this project may declare a
    colour, size, radius or type style.
    ==============================================================================================

    Dark mode is [data-theme="dark"] on <html>, a separate set of values rather than a filter over
    light. App.razor sets the attribute before first paint.

    The shell (SidebarNav, PageHeader) follows HCI Dialer's console. The pages do not: they are the
    portal design's own, on the canvas linked from docs/ADMIN-PORTAL-PLAN.md.
*/

/* ===================================================================== tokens, from HCI York -- */

:root {
  --canvas: #f2f5f7;
  --surface: #ffffff;
  --surface-sunken: #eaeff2;
  --surface-accent: #e6f3f5;
  --surface-hover: #eaeff2;

  --border: #c3cfd5;
  --border-strong: #7e9099;
  --divider: #e8eef1;

  --text: #142027;
  --text-secondary: #47606c;
  --text-muted: #566a74;
  --text-placeholder: #5f757f;

  --accent: #00a1b0;
  --accent-text: #00707c;
  --accent-strong: #005a64;
  --on-accent: #ffffff;
  --accent-quiet-text: #00707c;

  --danger: #a93c30;
  --success: #00707c;

  --chart-1: #00707c;
  --chart-2: #00a1b0;
  --chart-3: #8fc6cc;
  --chart-4: #cfe3e6;
  --chart-track: #eaeff2;

  --focus-ring: #00707c;

  --font-sans: "Space Grotesk", "Helvetica Neue", Arial, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --size-display: 30px;  --lh-display: 1.15;  --ls-display: -0.02em;
  --size-title: 17px;    --lh-title: 1.25;    --ls-title: -0.01em;
  --size-metric: 24px;   --lh-metric: 1.1;
  --size-section: 13px;  --lh-section: 1.3;
  --size-body: 13px;     --lh-body: 1.55;
  --size-body-lg: 14px;  --lh-body-lg: 1.65;
  --size-label: 11px;    --lh-label: 1.4;
  --size-meta: 10px;     --lh-meta: 1.4;
  --size-micro: 9px;     --lh-micro: 1.4;

  --weight-regular: 400;
  --weight-medium: 500;
  --weight-bold: 700;

  --ls-caps: 0.12em;
  --ls-caps-tight: 0.1em;

  --space-1: 4px;   --space-2: 6px;   --space-3: 8px;   --space-4: 10px;
  --space-5: 12px;  --space-6: 14px;  --space-7: 16px;  --space-8: 18px;
  --space-9: 20px;  --space-10: 22px; --space-12: 28px; --space-14: 36px;
  --space-16: 48px;

  --gap-grid: var(--space-5);
  --gap-stack: var(--space-8);
  --pad-card: 13px 14px;
  --pad-card-lg: 15px 16px;
  --pad-row: 10px 16px;
  --pad-row-compact: 6px 16px;
  --pad-page: var(--space-9) var(--space-10);
  --pad-control: 8px 11px;
  --pad-chip: 5px 9px;
  --sidebar-width: 210px;

  /*
      The height the sidebar's brand block and the page header BOTH take, so the rule under one
      lines up with the rule under the other.

      Stated once because it was wrong twice. Each block used to size itself from its own padding
      and contents: the header holds a 17px title over a 10px mono context line and came out 66px,
      the brand block holds one 14px line and came out 52px. They were only ever going to agree by
      coincidence, and they did not. 66px is the header's natural height, so this is the value it
      already had - what changed is that the sidebar is told it too.
  */
  --header-height: 66px;

  /* The HCI York mark's two inks. Fixed artwork colours, the same in both themes. */
  --logo-teal: #00a1b0;
  --logo-grey: #bbc6c3;


  --radius-xs: 3px;
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 10px;
  --radius-full: 50%;

  --border-width: 1px;
  --shadow-none: none;
  --transition: 120ms ease;
}

[data-theme="dark"] {
  --canvas: #0b1216;
  --surface: #121b21;
  --surface-sunken: #18242b;
  --surface-accent: #08313a;
  --surface-hover: #18242b;

  --border: #33444c;
  --border-strong: #5a6f79;
  --divider: #1b262c;

  --text: #e4edf1;
  --text-secondary: #a7b8c0;
  --text-muted: #8ea3ad;
  --text-placeholder: #738992;

  --accent: #3ec8d3;
  --accent-text: #3ec8d3;
  --accent-strong: #2b8e9b;
  --on-accent: #04262b;
  --accent-quiet-text: #9adde4;

  --danger: #f08d7f;
  --success: #3ec8d3;

  --chart-1: #3ec8d3;
  --chart-2: #2b8e9b;
  --chart-3: #1f5d66;
  --chart-4: #1f3d45;
  --chart-track: #18242b;

  --focus-ring: #3ec8d3;
}

/* ================================================================================ base -- */

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

body {
  margin: 0;
  background: var(--canvas);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--size-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent-text); text-decoration: none; }
a:hover { text-decoration: underline; }

:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

::placeholder { color: var(--text-placeholder); }

/* Anything a system measured. Sans is for anything a person wrote. */
.mono {
  font-family: var(--font-mono);
}

/* ============================================================================== layout -- */

.shell {
  display: grid;
  grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
  min-height: 100vh;
}

.shell-body {
  display: flex;
  min-width: 0;
  flex-direction: column;
}

.content {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--gap-stack);
  padding: var(--pad-page);
}

@media (max-width: 900px) {
  .shell {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ========================================================================= SidebarNav -- */

.sidebar {
  display: flex;
  flex-direction: column;
  border-right: var(--border-width) solid var(--border);
  background: var(--surface);
}

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: var(--space-4);

  /* Centred in a fixed height rather than padded to one: see --header-height. */
  height: var(--header-height);
  padding: 0 var(--space-6);
  border-bottom: var(--border-width) solid var(--border);
}

/* The HCI York mark. Its two inks are fixed artwork colours, identical in both themes. */
.brand-mark {
  width: 20px;
  height: 20px;
  flex: none;
}

.brand-words {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.brand-name {
  font-size: var(--size-body-lg);
  font-weight: var(--weight-bold);
  letter-spacing: var(--ls-title);
  line-height: 1.2;
}

.brand-product {
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--size-micro);
  letter-spacing: var(--ls-caps);
  line-height: var(--lh-micro);
  text-transform: uppercase;
}

.sidebar-sections {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--space-7);

  /* Top padding because the brand block now carries a rule under it, which it did not before. */
  padding: var(--space-6) var(--space-4);
}

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

.nav-section-label {
  margin: 0 0 var(--space-2);
  padding: 0 var(--space-3);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--size-micro);
  letter-spacing: var(--ls-caps);
  line-height: var(--lh-micro);
  text-transform: uppercase;
}

.nav-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-size: var(--size-body);
  text-decoration: none;
  transition: background-color var(--transition), color var(--transition);
}

.nav-item:hover {
  background: var(--surface-hover);
  text-decoration: none;
}

/* Active nav is a tinted fill with an accent label at weight 500. Never a bar. */
.nav-item.active {
  background: var(--surface-accent);
  color: var(--accent-text);
  font-weight: var(--weight-medium);
}

.nav-count {
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--size-meta);
}

/* The user block pins to the bottom of the sidebar. */
.sidebar-user {
  border-top: var(--border-width) solid var(--border);
  padding: var(--space-5) var(--space-6);
}

.user-row {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.user-avatar {
  display: grid;
  width: 28px;
  height: 28px;
  flex: none;
  border-radius: var(--radius-full);
  background: var(--surface-accent);
  color: var(--accent-text);
  font-size: var(--size-label);
  font-weight: var(--weight-bold);
  place-items: center;
}

.user-detail {
  min-width: 0;
}

.user-name {
  overflow: hidden;
  font-size: var(--size-body);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.user-role {
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--size-meta);
  line-height: var(--lh-meta);
}

.sidebar-user form {
  margin: 0;
}

.sidebar-user .button-row {
  margin-top: var(--space-4);
}

/* ========================================================================= PageHeader -- */

.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-7);
  border-bottom: var(--border-width) solid var(--border);

  /* The same fixed height as the sidebar's brand block: see --header-height. */
  height: var(--header-height);
  padding: 0 var(--space-10);
  background: var(--surface);
}

/*
    FocusOnNavigate moves focus to the title after every navigation, so a screen reader announces the
    new page. That focus is not one a person put there, so it draws no ring; a keyboard user tabbing
    lands on real controls, which still do.
*/
.page-title:focus,
.display:focus {
  outline: none;
}

.page-title {
  margin: 0;
  font-size: var(--size-title);
  font-weight: var(--weight-bold);
  letter-spacing: var(--ls-title);
  line-height: var(--lh-title);
}

/* Contract, then site, then ISO period. In mono. */
.page-meta {
  margin: var(--space-1) 0 0;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--size-meta);
  line-height: var(--lh-meta);
}

.page-actions {
  display: flex;
  flex: none;
  gap: var(--space-3);
}

/* =============================================================================== Card -- */

.card {
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
}

.card-padded {
  padding: var(--pad-card-lg);
}

/* At most one tinted card per row. */
.card-accent {
  background: var(--surface-accent);
}

.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-7);
  padding: var(--pad-card-lg);
}

.card-head + .card-body,
.card-head + .table-wrap {
  border-top: var(--border-width) solid var(--border);
}

.card-title {
  margin: 0;
  font-size: var(--size-section);
  font-weight: var(--weight-bold);
  line-height: var(--lh-section);
}

.card-body {
  padding: var(--pad-card-lg);
}

.card-body > :first-child { margin-top: 0; }
.card-body > :last-child { margin-bottom: 0; }

.prose {
  max-width: 78ch;
  font-size: var(--size-body-lg);
  line-height: var(--lh-body-lg);
}

.note {
  color: var(--text-muted);
  font-size: var(--size-label);
  line-height: var(--lh-label);
}

/* =========================================================================== StatCard -- */

/* Four across on the wide shell, two across below 900px. */
.stat-row {
  display: grid;
  gap: var(--gap-grid);
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

@media (max-width: 900px) {
  .stat-row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.stat {
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--pad-card);
  background: var(--surface);
}

.stat-accent {
  background: var(--surface-accent);
}

.stat-label {
  color: var(--text-muted);
  font-size: var(--size-label);
  line-height: var(--lh-label);
}

.stat-accent .stat-label,
.stat-accent .stat-delta {
  color: var(--accent-quiet-text);
}

.stat-value {
  margin: var(--space-2) 0 0;
  font-family: var(--font-mono);
  font-size: var(--size-metric);
  line-height: var(--lh-metric);
}

/* Every delta carries its comparison. */
.stat-delta {
  margin: var(--space-2) 0 0;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--size-meta);
  line-height: var(--lh-meta);
}

.stat-delta-negative { color: var(--danger); }
.stat-delta-positive { color: var(--success); }

/* ============================================================================== Badge -- */

.badge {
  display: inline-block;
  font-size: var(--size-label);
  line-height: var(--lh-label);
}

/* neutral and accent are boxed. */
.badge-neutral,
.badge-accent {
  border-radius: var(--radius-sm);
  padding: var(--pad-chip);
}

.badge-neutral {
  background: var(--surface-sunken);
  color: var(--text-secondary);
}

.badge-accent {
  background: var(--surface-accent);
  color: var(--accent-text);
}

/* positive and negative are bare bold text, because boxes make dense rows noisy. */
.badge-positive {
  color: var(--success);
  font-weight: var(--weight-bold);
}

.badge-negative {
  color: var(--danger);
  font-weight: var(--weight-bold);
}

/* A period selector. DESIGN.md's FilterChips. */
.chip-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.chip {
  border: var(--border-width) solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: var(--pad-chip);
  background: var(--surface);
  color: var(--text);
  font-size: var(--size-label);
  line-height: var(--lh-label);
  transition: background var(--transition), color var(--transition);
}

.chip:hover { background: var(--surface-hover); }

/* --accent-text, never --accent: this fill sits behind a label. */
.chip-active {
  border-color: var(--accent-text);
  background: var(--accent-text);
  color: var(--on-accent);
  font-weight: var(--weight-medium);
}

.chip:disabled { opacity: 0.45; cursor: not-allowed; }

/* The analysis row DESIGN.md specifies: 2.1fr beside 1fr, collapsing on a narrow window. */
.analysis-row {
  display: grid;
  grid-template-columns: 2.1fr 1fr;
  align-items: start;
  gap: var(--gap-grid);
}

/*
    Wider than HCI Dialer's breakpoint, because the portal's tables are wider: a key's dates and a
    delivery's timestamp are mono and do not truncate gracefully. Below this the table gets the whole
    width and its side card sits under it.
*/
@media (max-width: 1440px) {
  .analysis-row {
    grid-template-columns: minmax(0, 1fr);
  }
}

.table-wrap {
  overflow-x: auto;
}

.table {
  width: 100%;
  border-collapse: collapse;

  /* 12px, between label and body, as the design system's DataTable sets its cells. */
  font-size: 12px;
  table-layout: fixed;
}

.table th {
  border-bottom: var(--border-width) solid var(--border);
  padding: 9px 16px;
  font-size: var(--size-label);
  background: var(--surface-sunken);
  color: var(--text-secondary);
  font-weight: var(--weight-bold);
  text-align: left;
}

.table td {
  border-bottom: var(--border-width) solid var(--divider);
  padding: var(--pad-row);
}

.table-compact td,
.table-compact th {
  padding: var(--pad-row-compact);
}

.table tbody tr:last-child td {
  border-bottom: none;
}

.table tbody tr:hover {
  background: var(--surface-hover);
}

/* Cells truncate rather than wrap. */
.table td,
.table th {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cell-mono { font-family: var(--font-mono); }
.cell-muted { color: var(--text-muted); }
.cell-actions { text-align: right; white-space: nowrap; }

/* Footers are uppercase mono. */
.table-footer {
  border-top: var(--border-width) solid var(--border);
  padding: var(--pad-row);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--size-micro);
  letter-spacing: var(--ls-caps);
  line-height: var(--lh-micro);
  text-transform: uppercase;
}

/* ============================================================================ Button -- */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: var(--border-width) solid transparent;
  border-radius: var(--radius-md);
  padding: 9px 14px;
  background: none;
  color: var(--text);
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: 12px;
  line-height: 1.2;
  text-decoration: none;
  transition: background-color var(--transition), color var(--transition),
    border-color var(--transition);
}

.button:hover { text-decoration: none; }

.button-sm { padding: 6px 10px; }
.button-lg { padding: 11px 18px; }

/* The primary fill is --accent-text, never raw --accent. One primary per view. */
.button-primary {
  background: var(--accent-text);
  color: var(--on-accent);
}

.button-primary:hover {
  background: var(--accent-strong);
}

.button-secondary {
  border-color: var(--border-strong);
  background: var(--surface);
}

.button-secondary:hover {
  background: var(--surface-hover);
}

/* A teal label with no chrome. For table row actions. */
.button-quiet {
  padding: 6px 8px;
  color: var(--accent-text);
}

.button-quiet:hover {
  background: var(--surface-hover);
}

/* Bordered, with a --danger label. Never a red fill. */
.button-danger {
  border-color: var(--border-strong);
  background: var(--surface);
  color: var(--danger);
}

.button-danger:hover {
  background: var(--surface-hover);
}

.button:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

.button-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* ================================================================ Input and Select -- */

.field {
  display: block;
  max-width: 420px;
  margin-bottom: var(--space-7);
}

.field-label {
  display: block;
  margin-bottom: var(--space-2);
  color: var(--text-muted);
  font-size: var(--size-label);
  line-height: var(--lh-label);
}

.field-control {
  width: 100%;
  border: var(--border-width) solid var(--border-strong);
  border-radius: var(--radius-md);
  padding: var(--pad-control);
  background: var(--surface);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 12px;
}

.field-control-mono {
  font-family: var(--font-mono);
}

/* The caret, drawn from two gradients. */
select.field-control {
  appearance: none;
  padding-right: var(--space-12);
  background-image:
    linear-gradient(45deg, transparent 50%, var(--text-muted) 50%),
    linear-gradient(135deg, var(--text-muted) 50%, transparent 50%);
  background-position: calc(100% - 16px) calc(50% + 2px), calc(100% - 11px) calc(50% + 2px);
  background-repeat: no-repeat;
  background-size: 5px 5px, 5px 5px;
}

.field-hint {
  margin: var(--space-2) 0 0;
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--size-meta);
  line-height: var(--lh-meta);
}

.field-invalid .field-control {
  border-color: var(--danger);
}

.field-invalid .field-hint {
  color: var(--danger);
}

.form-error {
  margin: 0 0 var(--space-7);
  max-width: 420px;
  border: var(--border-width) solid var(--danger);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  color: var(--danger);
  font-size: var(--size-body);
}

/* ============================================================== display and eyebrow -- */

/* Login and empty-state headline. One per screen. */
.display {
  margin: 0 0 var(--space-5);
  font-size: var(--size-display);
  font-weight: var(--weight-bold);
  letter-spacing: var(--ls-display);
  line-height: var(--lh-display);
}

.eyebrow {
  margin: 0 0 var(--space-2);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--size-micro);
  letter-spacing: var(--ls-caps);
  line-height: var(--lh-micro);
  text-transform: uppercase;
}

/* ======================================================================== the reveal -- */

/*
    The one-time key reveal. A tinted card rather than anything louder: DESIGN.md has no amber and
    no warning colour, and --danger is for breach and destructive actions only.
*/
.secret {
  display: block;
  overflow-wrap: anywhere;
  margin: var(--space-5) 0;
  border: var(--border-width) solid var(--border-strong);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  background: var(--surface);
  font-family: var(--font-mono);
  font-size: var(--size-body);
  user-select: all;
}

/* ============================================================== a centred single card -- */

/* Sign-in, signed-out, not-found and error: no shell, one card, nothing to navigate. */
.solo {
  display: grid;
  min-height: 100vh;
  padding: var(--space-16) var(--space-10);
  place-items: start center;
}

.solo-card {
  width: 100%;
  max-width: 520px;
}

/* ========================================================================== facts list -- */

.facts {
  display: grid;
  gap: var(--space-5);
  margin: 0;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}

.facts dt {
  color: var(--text-muted);
  font-size: var(--size-label);
  line-height: var(--lh-label);
}

.facts dd {
  overflow-wrap: anywhere;
  margin: var(--space-1) 0 0;
  font-family: var(--font-mono);
  font-size: var(--size-body);
}

/* ===================================================================== the portal's own -- */

/* The page header's title, with the way back to the list in front of it. */
.page-title-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

.page-crumb {
  color: var(--text-muted);
  font-size: var(--size-body);
}

.page-crumb:hover { color: var(--text); }

.page-crumb-separator {
  color: var(--text-muted);
}

/* A card head with a line of explanation under its title. */
.card-head-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.card-subtitle {
  margin: 0;
  color: var(--text-muted);
  font-size: var(--size-label);
  line-height: var(--lh-label);
}

/* A table row that opens something. The whole row is the target. */
.row-link {
  cursor: pointer;
}

.row-link:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: -2px;
}

.cell-strong { font-weight: var(--weight-bold); }
.cell-positive { color: var(--success); font-weight: var(--weight-bold); }
.cell-negative { color: var(--danger); font-weight: var(--weight-bold); }
.row-retired td { color: var(--text-secondary); }

.table-footer-split {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
}

.pager {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* The search field in a page header. */
.search {
  width: 240px;
  margin: 0;
}

/* A registration's facts, label beside value. */
.kv {
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr);
  row-gap: var(--space-4);
  column-gap: var(--space-4);
  margin: 0;
  font-size: 12px;
}

.kv dt {
  color: var(--text-muted);
  font-size: var(--size-label);
  line-height: var(--lh-body);
}

.kv dd {
  overflow-wrap: anywhere;
  margin: 0;
}

.kv dd.mono { font-size: var(--size-label); }

/* A stored value shown but not editable, such as a secret's first characters. */
.readout {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--pad-control);
  background: var(--surface-sunken);
  font-family: var(--font-mono);
  font-size: var(--size-label);
}

.readout-meta {
  color: var(--text-muted);
  font-size: var(--size-meta);
}

.stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-7);
}

.stack .field { margin-bottom: 0; max-width: none; }

.inline-status {
  margin: 0;
  color: var(--text-secondary);
  font-size: var(--size-label);
}

.inline-status-negative { color: var(--danger); }

/* ============================================================================== Modal -- */

/*
    A dialog over the page. The backdrop is the only translucent thing in the system, and it carries
    no text. No shadow: the dialog reads as a surface on the dimmed page, as a card reads on canvas.
*/
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 10;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  overflow-y: auto;
  padding: 12vh var(--space-10) var(--space-10);
  background: rgba(20, 32, 39, 0.45);
}

.modal {
  width: 100%;
  max-width: 460px;
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
}

.modal-wide { max-width: 540px; }

.modal-head {
  display: flex;
  flex-direction: column;
  gap: 2px;
  border-bottom: var(--border-width) solid var(--border);
  padding: var(--space-7) var(--space-9);
}

.modal-title {
  margin: 0;
  font-size: var(--size-title);
  font-weight: var(--weight-bold);
  letter-spacing: var(--ls-title);
  line-height: var(--lh-title);
}

.modal-subtitle {
  margin: 0;
  color: var(--text-muted);
  font-size: 12px;
}

.modal-subtitle.mono { font-size: var(--size-meta); }

.modal-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  padding: var(--space-8) var(--space-9);
}

.modal-body .field { margin-bottom: 0; max-width: none; }
.modal-body .form-error { margin: 0; max-width: none; }

.modal-body p {
  margin: 0;
  color: var(--text-secondary);
  font-size: 12px;
}

.modal-foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-4);
  border-top: var(--border-width) solid var(--border);
  padding: var(--space-6) var(--space-9);
}

/* The one-time reveal of a key or a signing secret, inside a dialog. */
.reveal {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-4) 11px;
  background: var(--surface-accent);
}

.reveal code {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
  color: var(--text);
  font-family: var(--font-mono);
  font-size: var(--size-label);
  line-height: 1.5;
  user-select: all;
}

.checkbox {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  font-size: 12px;
  cursor: pointer;
}

.checkbox input {
  width: 15px;
  height: 15px;
  margin: 0;
  accent-color: var(--accent-text);
}

/* ============================================================================ Sign in -- */

.sign-in {
  display: flex;
  flex-direction: column;
  gap: var(--space-9);
  max-width: 420px;
  margin: 0 auto;
  padding: var(--space-16);
  border-radius: var(--radius-lg);
}

.sign-in .display { margin: 0 0 var(--space-2); }

.sign-in-lede {
  margin: 0;
  color: var(--text-secondary);
}

.sign-in-note {
  margin: 0;
  color: var(--text-secondary);
  font-family: var(--font-sans);
  font-size: 12px;
}

.sign-in-button { width: 100%; }

.sign-in-foot {
  margin: 0;
  font-size: var(--size-meta);
  letter-spacing: 0;
  text-transform: none;
}

/* The sign-in and refusal pages centre their card in the window. */
.solo-centred { place-items: center; }

.access-actions { margin-top: var(--space-7); }

/* A suspended registration's reason, above everything else on its page. */
.callout {
  border: var(--border-width) solid var(--danger);
  border-radius: var(--radius-md);
  padding: var(--space-5) var(--space-7);
  background: var(--surface);
  color: var(--text);
  font-size: var(--size-body);
}

.callout strong { color: var(--danger); }

.empty {
  padding: var(--space-14) var(--space-10);
  color: var(--text-secondary);
  text-align: center;
}

/* A quiet row action that cannot be undone: a danger label, still no chrome. */
.button-quiet-danger { color: var(--danger); }

/* For a screen reader and nobody else: a column header over a column of buttons. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* A row's buttons are never truncated: an ellipsis on "Revoke" leaves nothing to press. */
.table td.cell-actions {
  overflow: visible;
  padding-left: var(--space-3);
  text-overflow: clip;
}
