/*
 * The operator console's stylesheet.
 *
 * Served as ONE file, GET /static/console.css, rather than inlined,
 * because the console's Content-Security-Policy allows style only from 'self'
 * files. It is kept here as several files split by concern, and static.go
 * joins them in the cascade order stylesheetParts declares -- this one first,
 * responsive.css last. The class names are the contract with templates/*.html.
 *
 * Direction: a calm operator console. Neutral surfaces, one indigo accent, and
 * green/amber/red reserved for status, so the pills that carry meaning are the
 * only colour on the page. No web fonts, no external assets.
 */

/* Design tokens: the light palette, and the dark one for the media query and for an explicit data-theme. */

/* ---- tokens ------------------------------------------------------------- */

:root {
  color-scheme: light dark;

  --bg: #f6f7f9;
  --surface: #ffffff;
  --surface-2: #f1f3f6;
  --row-hover: #f8f9fb;
  --border: #e3e6eb;
  --border-strong: #cfd4dc;
  --control-border: #858d9a;

  --text: #161a22;
  --text-muted: #5b6472;
  --text-faint: #646d7a;

  --accent: #4f46e5;
  --accent-hover: #4338ca;
  --accent-soft: #eef0ff;
  --accent-border: #d5d8fb;
  --accent-wash: rgba(79, 70, 229, 0.09);
  --on-accent: #ffffff;

  --success: #137a3b;
  --success-soft: #e8f6ec;
  --success-border: #c4e7cf;
  --warning: #a14a07;
  --warning-soft: #fdf3e3;
  --warning-border: #f3dcb5;
  --danger: #c62828;
  --danger-hover: #ad1f1f;
  --danger-soft: #fdecec;
  --danger-border: #f5c9c9;

  --shadow-card: 0 1px 2px rgba(16, 24, 40, 0.04), 0 1px 3px rgba(16, 24, 40, 0.03);
  --shadow-dialog: 0 24px 48px -12px rgba(16, 24, 40, 0.28), 0 2px 6px rgba(16, 24, 40, 0.08);
  --backdrop: rgba(13, 15, 20, 0.45);

  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --radius-control: 6px;
  --radius-callout: 10px;
  --radius-card: 12px;
  --ease: 140ms ease;
}

/* The dark palette, twice: once for the media query (unless the page pins
   light), once for an explicit data-theme="dark". The console itself never
   sets data-theme; the attribute exists so the preview harness can render
   each theme in a renderer that cannot emulate the media query. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0d0f14;
    --surface: #151821;
    --surface-2: #1c202b;
    --row-hover: #191d27;
    --border: #262b37;
    --border-strong: #343a48;
    --control-border: #666e82;

    --text: #e8ebf1;
    --text-muted: #a2abb9;
    --text-faint: #8a93a3;

    --accent: #8b93ff;
    --accent-hover: #a5abff;
    --accent-soft: #20234a;
    --accent-border: #343a78;
    --accent-wash: rgba(139, 147, 255, 0.11);
    --on-accent: #0d0f14;

    --success: #4ade80;
    --success-soft: #123122;
    --success-border: #1d4a33;
    --warning: #fbbf24;
    --warning-soft: #3a2c10;
    --warning-border: #57421a;
    --danger: #f87171;
    --danger-hover: #fca5a5;
    --danger-soft: #3b1618;
    --danger-border: #5c2427;

    --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-dialog: 0 24px 48px -12px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.02);
    --backdrop: rgba(0, 0, 0, 0.6);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --bg: #0d0f14;
  --surface: #151821;
  --surface-2: #1c202b;
  --row-hover: #191d27;
  --border: #262b37;
  --border-strong: #343a48;
  --control-border: #666e82;

  --text: #e8ebf1;
  --text-muted: #a2abb9;
  --text-faint: #8a93a3;

  --accent: #8b93ff;
  --accent-hover: #a5abff;
  --accent-soft: #20234a;
  --accent-border: #343a78;
  --accent-wash: rgba(139, 147, 255, 0.11);
  --on-accent: #0d0f14;

  --success: #4ade80;
  --success-soft: #123122;
  --success-border: #1d4a33;
  --warning: #fbbf24;
  --warning-soft: #3a2c10;
  --warning-border: #57421a;
  --danger: #f87171;
  --danger-hover: #fca5a5;
  --danger-soft: #3b1618;
  --danger-border: #5c2427;

  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-dialog: 0 24px 48px -12px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.02);
  --backdrop: rgba(0, 0, 0, 0.6);
}

:root[data-theme="light"] {
  color-scheme: light;
}

/* Base element styles, icons, the brand, and the two page shells. */

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

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

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 15px/1.55 var(--font-sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1,
h2,
h3,
p,
dl,
dd,
figure {
  margin: 0;
}

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

a:hover {
  text-decoration: underline;
  text-underline-offset: 2px;
}

code,
.mono {
  font-family: var(--font-mono);
  font-size: 0.92em;
}

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

[hidden] {
  display: none !important;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

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

.faint {
  color: var(--text-faint);
}

time {
  white-space: nowrap;
}

/* ---- icons -------------------------------------------------------------- */

/* Inline SVG icons carry no presentation attributes of their own: stroke and
   fill come from here, so the markup never spells a colour. */
.icon {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.icon-bold {
  stroke-width: 3;
}

/* ---- brand -------------------------------------------------------------- */

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--text);
  font-weight: 650;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

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

.brand-mark {
  flex: none;
  width: 28px;
  height: 28px;
  color: var(--accent);
}

.brand-mark .tile {
  fill: currentColor;
}

.brand-mark .glyph {
  fill: none;
  stroke: var(--on-accent);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.brand-name {
  font-size: 15px;
}

.brand-product {
  color: var(--text-muted);
  font-weight: 500;
}

/* ---- app shell (signed-in pages) --------------------------------------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.topbar-inner {
  display: flex;
  align-items: center;
  gap: 16px;
  max-width: 72rem;
  height: 56px;
  margin: 0 auto;
  padding: 0 24px;
}

.topbar-divider {
  flex: none;
  width: 1px;
  height: 20px;
  background: var(--border-strong);
}

.crumbs {
  flex: 1;
  min-width: 0;
}

.crumbs ol {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 14px;
}

.crumbs li {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  color: var(--text-muted);
  white-space: nowrap;
}

.crumbs li + li::before {
  content: "/";
  color: var(--border-strong);
}

.crumbs a {
  color: var(--text-muted);
}

.crumbs a:hover {
  color: var(--text);
}

.crumbs li:last-child {
  overflow: hidden;
  color: var(--text);
  font-weight: 550;
}

.crumbs li:last-child span {
  overflow: hidden;
  text-overflow: ellipsis;
}

.topbar-actions {
  display: flex;
  flex: none;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

.topbar-actions form {
  margin: 0;
}

.page {
  max-width: 72rem;
  margin: 0 auto;
  padding: 32px 24px 72px;
}

.page-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px 24px;
  margin-bottom: 24px;
}

.page-heading {
  min-width: 0;
}

.page-title {
  font-size: 24px;
  font-weight: 650;
  line-height: 1.25;
  letter-spacing: -0.015em;
  overflow-wrap: anywhere;
}

.page-sub {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
  color: var(--text-muted);
  font-size: 14px;
}

.stack {
  display: grid;
  gap: 24px;
}

.stack > * {
  min-width: 0;
}

.page-narrow {
  max-width: 48rem;
  margin: 0 auto;
}

/* ---- auth shell (login, enrolment, 2FA) -------------------------------- */

.auth-body {
  min-height: 100vh;
  background:
    radial-gradient(56rem 32rem at 50% -8rem, var(--accent-wash), transparent 70%),
    var(--bg);
  background-repeat: no-repeat;
}

.auth {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 48px 16px;
}

.auth-brand {
  margin-bottom: 24px;
}

.auth-brand .brand-mark {
  width: 32px;
  height: 32px;
}

.auth-card {
  width: 100%;
  max-width: 26rem;
  padding: 32px;
}

.auth-card-wide {
  max-width: 44rem;
}

.auth-title {
  font-size: 20px;
  font-weight: 650;
  line-height: 1.3;
  letter-spacing: -0.01em;
}

.auth-lede {
  margin-top: 6px;
  color: var(--text-muted);
  font-size: 14px;
}

.auth-card .callout {
  margin-top: 20px;
}

.auth-card .form {
  margin-top: 24px;
}

.auth-foot {
  margin-top: 24px;
  color: var(--text-faint);
  font-size: 12px;
  text-align: center;
}

.auth-alt {
  margin-top: 20px;
  font-size: 13px;
  text-align: center;
}

.account-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  margin-top: 14px;
  padding: 3px 10px 3px 8px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: 13px;
}

.account-chip svg {
  flex: none;
  width: 14px;
  height: 14px;
}

.account-chip span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.steps {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 24px;
  padding: 0;
  list-style: none;
  color: var(--text-muted);
  font-size: 13px;
}

.step {
  display: flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}

.step + .step::before {
  content: "";
  width: 28px;
  height: 1px;
  margin-right: 2px;
  background: var(--border-strong);
}

.step-num {
  display: inline-grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border: 1px solid var(--border-strong);
  border-radius: 50%;
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.step-num svg {
  width: 12px;
  height: 12px;
}

.step.is-done .step-num {
  border-color: transparent;
  background: var(--success-soft);
  color: var(--success);
}

.step.is-active {
  color: var(--text);
  font-weight: 600;
}

.step.is-active .step-num {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--on-accent);
}

/* Keeps a run of text on one line -- e.g. a command's "| sh" with the token
   characters before it -- while the text around it may still wrap. */
.nowrap {
  white-space: nowrap;
}

/* Form fields, buttons and the invite-kind choice cards. */

/* ---- forms -------------------------------------------------------------- */

.form {
  display: grid;
  gap: 16px;
}

.field {
  display: grid;
  gap: 6px;
}

.field label,
.label {
  color: var(--text);
  font-size: 13px;
  font-weight: 600;
}

.input {
  width: 100%;
  height: 40px;
  padding: 0 12px;
  border: 1px solid var(--control-border);
  border-radius: var(--radius-control);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 15px;
  transition: border-color var(--ease), box-shadow var(--ease);
}

.input:hover {
  border-color: var(--text-muted);
}

.input:focus-visible {
  border-color: var(--accent);
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.input::placeholder {
  color: var(--text-faint);
}

.input-otp {
  height: 56px;
  padding: 0 0 0 0.45em;
  font-family: var(--font-mono);
  font-size: 26px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.45em;
  text-align: center;
}

.input-search {
  max-width: 18rem;
  height: 36px;
  padding-left: 34px;
  font-size: 14px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%238a93a1' stroke-width='2' stroke-linecap='round' viewBox='0 0 24 24'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E");
  background-position: 11px center;
  background-repeat: no-repeat;
}

.hint {
  color: var(--text-muted);
  font-size: 13px;
}

/* ---- form actions ------------------------------------------------------- */

.form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 16px;
}

/* ---- buttons ------------------------------------------------------------ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 36px;
  padding: 0 14px;
  border: 1px solid transparent;
  border-radius: var(--radius-control);
  font: inherit;
  font-size: 14px;
  font-weight: 550;
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  appearance: none;
  transition: background-color var(--ease), border-color var(--ease), color var(--ease), box-shadow var(--ease);
}

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

.btn svg {
  flex: none;
  width: 16px;
  height: 16px;
}

.btn-primary {
  background: var(--accent);
  color: var(--on-accent);
}

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

.btn-secondary {
  border-color: var(--control-border);
  background: var(--surface);
  color: var(--text);
  box-shadow: 0 1px 0 rgba(16, 24, 40, 0.03);
}

.btn-secondary:hover {
  border-color: var(--text-muted);
  background: var(--surface-2);
}

.btn-ghost {
  background: transparent;
  color: var(--text-muted);
}

.btn-ghost:hover {
  background: var(--surface-2);
  color: var(--text);
}

.btn-danger {
  border-color: var(--danger-border);
  background: var(--surface);
  color: var(--danger);
}

.btn-danger:hover {
  border-color: var(--danger);
  background: var(--danger-soft);
}

.btn-danger-solid {
  background: var(--danger);
  color: #ffffff;
}

.btn-danger-solid:hover {
  background: var(--danger-hover);
}

:root[data-theme="dark"] .btn-danger-solid {
  color: #0d0f14;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .btn-danger-solid {
    color: #0d0f14;
  }
}

.btn-sm {
  height: 30px;
  padding: 0 10px;
  font-size: 13px;
}

.btn-lg {
  height: 42px;
  font-size: 15px;
}

.btn-block {
  width: 100%;
}

.btn:disabled,
.btn[aria-busy="true"] {
  opacity: 0.6;
  cursor: not-allowed;
}

.btn[aria-busy="true"]::after {
  content: "";
  width: 12px;
  height: 12px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: console-spin 700ms linear infinite;
}

@keyframes console-spin {
  to {
    transform: rotate(360deg);
  }
}

/* ---- choice cards (invite kind) ---------------------------------------- */

.choice-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin: 0;
  padding: 0;
  border: 0;
}

.choice {
  position: relative;
  display: block;
  padding: 14px 16px 14px 44px;
  border: 1px solid var(--control-border);
  border-radius: var(--radius-callout);
  background: var(--surface);
  cursor: pointer;
  transition: border-color var(--ease), background-color var(--ease), box-shadow var(--ease);
}

.choice:hover {
  border-color: var(--text-muted);
}

/* The radio is drawn here rather than left to the browser: a native radio
   styled only by accent-color rendered its checked state as a bare dot with no
   ring, and its contrast on the accent-tinted card could not be known. Drawn,
   the ring uses --control-border (3:1 or better on the surface) and the checked
   state is a thick accent ring around a surface dot, in both palettes. */
.choice input {
  position: absolute;
  top: 16px;
  left: 16px;
  width: 18px;
  height: 18px;
  margin: 0;
  border: 1.5px solid var(--control-border);
  border-radius: 50%;
  background: var(--surface);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color var(--ease), border-width var(--ease);
}

.choice input:checked {
  border: 5px solid var(--accent);
  background: var(--surface);
}

.choice input:focus-visible {
  outline: none;
}

.choice:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--accent);
}

.choice:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.choice-title {
  display: block;
  font-size: 14px;
  font-weight: 600;
}

.choice-text {
  display: block;
  margin-top: 2px;
  color: var(--text-muted);
  font-size: 13px;
}

.choice-meta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 500;
}

.choice-meta svg {
  width: 13px;
  height: 13px;
}

/* Cards, stat tiles, pills, callouts, the confirmation dialog, secret fields, empty states, disclosures and facts lists. */

/* ---- cards -------------------------------------------------------------- */

.card {
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface);
  box-shadow: var(--shadow-card);
}

.card-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 16px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
}

.card-title {
  font-size: 15px;
  font-weight: 600;
  line-height: 1.4;
}

.card-meta {
  color: var(--text-muted);
  font-size: 13px;
}

.card-body {
  padding: 20px;
}

.card-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 20px;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}

.card-footer .hint {
  flex: 1 1 16rem;
}

/* ---- stat tiles --------------------------------------------------------- */

.stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  margin-bottom: 24px;
}

.stat {
  padding: 18px 20px;
}

.stat-label {
  color: var(--text-muted);
  font-size: 13px;
  font-weight: 500;
}

.stat-value {
  margin-top: 6px;
  display: flex;
  align-items: center;
  min-height: 38px;
  font-size: 30px;
  font-weight: 650;
  line-height: 1.15;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

.stat-value.is-version {
  font-family: var(--font-mono);
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.stat-value.is-empty {
  color: var(--text-faint);
  font-size: 24px;
  font-weight: 500;
}

.stat-sub {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
  min-height: 22px;
  margin-top: 8px;
  color: var(--text-muted);
  font-size: 13px;
}

/* ---- pills -------------------------------------------------------------- */

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 22px;
  padding: 0 9px;
  border: 1px solid transparent;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  vertical-align: middle;
}

.pill-dot::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

.pill-mono {
  font-family: var(--font-mono);
  font-weight: 500;
}

.pill-accent {
  border-color: var(--accent-border);
  background: var(--accent-soft);
  color: var(--accent);
}

.pill-success {
  border-color: var(--success-border);
  background: var(--success-soft);
  color: var(--success);
}

.pill-neutral {
  border-color: var(--border);
  background: var(--surface-2);
  color: var(--text-muted);
}

.pill-warning {
  border-color: var(--warning-border);
  background: var(--warning-soft);
  color: var(--warning);
}

.pill-danger {
  border-color: var(--danger-border);
  background: var(--danger-soft);
  color: var(--danger);
}

.tag {
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding: 0 7px;
  border-radius: 5px;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  vertical-align: middle;
}

.handle {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  background: var(--surface-2);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 12.5px;
}

/* ---- callouts ----------------------------------------------------------- */

.callout {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-callout);
  background: var(--surface-2);
  color: var(--text);
  font-size: 14px;
  line-height: 1.5;
}

.callout-icon {
  flex: none;
  width: 18px;
  height: 18px;
  margin-top: 1px;
}

.callout-content {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.callout-title {
  font-weight: 600;
}

.callout-info {
  border-color: var(--accent-border);
  background: var(--accent-soft);
}

.callout-info .callout-icon {
  color: var(--accent);
}

.callout-success {
  border-color: var(--success-border);
  background: var(--success-soft);
}

.callout-success .callout-icon {
  color: var(--success);
}

.callout-warning {
  border-color: var(--warning-border);
  background: var(--warning-soft);
}

.callout-warning .callout-icon {
  color: var(--warning);
}

.callout-danger {
  border-color: var(--danger-border);
  background: var(--danger-soft);
}

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

.page > .callout {
  margin-bottom: 24px;
}

/* ---- confirmation dialog ------------------------------------------------ */

dialog.confirm {
  width: min(28rem, calc(100vw - 32px));
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-dialog);
}

dialog.confirm::backdrop {
  background: var(--backdrop);
}

.confirm-form {
  margin: 0;
  padding: 22px 22px 18px;
}

.confirm-title {
  font-size: 17px;
  font-weight: 600;
  line-height: 1.35;
  overflow-wrap: anywhere;
}

.confirm-body {
  margin-top: 8px;
  color: var(--text-muted);
  font-size: 14px;
  overflow-wrap: anywhere;
}

.confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 22px;
}

/* ---- secret / code field ------------------------------------------------ */

.secret-block + .secret-block {
  margin-top: 16px;
}

.secret-label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 6px;
  font-size: 13px;
  font-weight: 600;
}

.secret {
  display: flex;
  align-items: stretch;
  overflow: hidden;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--surface-2);
}

.secret-value {
  flex: 1;
  min-width: 0;
  padding: 11px 12px;
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 13.5px;
  line-height: 1.55;
  overflow-wrap: anywhere;
  word-break: break-all;
  user-select: all;
  -webkit-user-select: all;
}

.secret-value code {
  font-size: inherit;
}

.secret-lg .secret-value {
  font-size: 17px;
  word-break: normal;
}

/* Eight blocks of four read best as two rows of four. 19ch is exactly four
   blocks and their three spaces in the monospace face, so the fifth block
   always starts the second row; narrower columns still wrap sooner. */
.secret-lg .secret-value code {
  display: inline-block;
  max-width: 19.5ch;
}

.secret .btn-copy {
  flex: none;
  height: auto;
  min-width: 76px;
  border: 0;
  border-left: 1px solid var(--border-strong);
  border-radius: 0;
  background: var(--surface);
  color: var(--text);
}

.secret .btn-copy:hover {
  background: var(--surface-2);
}

.secret .btn-copy.is-copied {
  color: var(--success);
}

.copy-hint {
  margin-top: 6px;
  color: var(--text-muted);
  font-size: 12px;
}

/* ---- empty state -------------------------------------------------------- */

.empty {
  padding: 56px 24px;
  text-align: center;
}

.empty-title {
  font-size: 15px;
  font-weight: 600;
}

.empty-text {
  max-width: 34rem;
  margin: 6px auto 0;
  color: var(--text-muted);
  font-size: 14px;
}

/* A command in an empty state sits on its own line and may wrap anywhere:
   kept on one unbreakable line it overflowed narrow cards and was clipped. */
.empty-text code {
  display: block;
  width: fit-content;
  max-width: 100%;
  margin: 8px auto;
  padding: 4px 8px;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: var(--surface-2);
  color: var(--text);
  overflow-wrap: anywhere;
}

/* ---- disclosure (inactive tokens, otpauth URI) ------------------------- */

.disclosure {
  border-top: 1px solid var(--border);
}

.disclosure > summary {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 20px;
  color: var(--text-muted);
  font-size: 13px;
  font-weight: 550;
  list-style: none;
  cursor: pointer;
}

/* Both sit flush against a parent that clips its overflow (.card, .secret),
   where the global ring drawn 2px outside would lose its sides. */
.disclosure > summary:focus-visible,
.secret .btn-copy:focus-visible {
  outline-offset: -2px;
}

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

.disclosure > summary::before {
  content: "";
  width: 7px;
  height: 7px;
  margin: 0 2px 0 1px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  transition: transform var(--ease);
}

.disclosure[open] > summary::before {
  transform: rotate(45deg);
}

.disclosure > summary:hover {
  background: var(--row-hover);
  color: var(--text);
}

.disclosure[open] > summary {
  border-bottom: 1px solid var(--border);
}

.disclosure-plain {
  border-top: 0;
}

.disclosure-plain > summary {
  padding: 4px 0;
}

.disclosure-plain > summary:hover {
  background: transparent;
}

.disclosure-plain[open] > summary {
  border-bottom: 0;
}

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

.facts {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: 10px 24px;
  font-size: 14px;
}

.facts dt {
  color: var(--text-muted);
}

.facts dd {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* Tables, including the fixed-layout token tables. */

/* ---- tables ------------------------------------------------------------- */

.table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}

.table th {
  padding: 10px 20px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-align: left;
  text-transform: uppercase;
  white-space: nowrap;
}

.table td {
  padding: 12px 20px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}

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

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

.table .col-actions {
  width: 1%;
  text-align: right;
  white-space: nowrap;
}

.table .col-actions form {
  display: inline-block;
  margin: 0;
}

.table .col-num {
  text-align: right;
}

.table .col-chevron {
  width: 1%;
  padding-left: 0;
  color: var(--text-faint);
}

.table .col-chevron svg {
  display: block;
  width: 16px;
  height: 16px;
}

.cell-stack {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.cell-primary {
  color: var(--text);
  font-weight: 550;
}

.cell-secondary {
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 12.5px;
}

.cell-inline {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 6px 8px;
}

.version {
  font-family: var(--font-mono);
  font-size: 13.5px;
  font-weight: 500;
}

.token-id {
  font-family: var(--font-mono);
  font-size: 13px;
}

/* A row that is a link as a whole: the name is the real anchor and its
   ::after stretches over the row, so the target stays one focusable link. */
.row-link {
  position: relative;
}

.row-link:hover td {
  cursor: pointer;
}

.row-link:hover .cell-primary {
  color: var(--accent);
}

.row-link:hover .col-chevron {
  color: var(--text-muted);
}

.stretched {
  color: inherit;
}

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

.stretched::after {
  content: "";
  position: absolute;
  inset: 0;
}

.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

/* ---- token tables ------------------------------------------------------- */

/* The active and inactive token tables share one set of column widths, so
   the columns line up when the inactive table is expanded beneath. */
.table-fixed {
  min-width: 44rem;
  table-layout: fixed;
}

.col-w-token {
  width: 17%;
}

.col-w-kind {
  width: 15%;
}

.col-w-status {
  width: 15%;
}

.col-w-time {
  width: 18%;
}

.col-w-last {
  width: 17%;
}

.table-fixed td {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.table-muted td {
  color: var(--text-muted);
}

/* An active token's kind, repeated under its short id for phone widths where
   the Kind column is hidden (responsive.css). Hidden while the column shows. */
.token-kind-inline {
  display: none;
}

/* Rules that belong to one page: enrolment, the error page, the invite result. */

/* ---- enrolment ---------------------------------------------------------- */

.enroll-grid {
  display: grid;
  grid-template-columns: 13.5rem minmax(0, 1fr);
  gap: 28px;
  margin-top: 24px;
}

.qr-panel {
  display: grid;
  place-items: center;
  align-self: start;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: #ffffff;
}

.qr-panel svg {
  display: block;
  width: 100%;
  height: auto;
}

.qr-caption {
  margin-top: 8px;
  color: var(--text-muted);
  font-size: 12px;
  text-align: center;
}

.enroll-manual {
  display: grid;
  align-content: start;
  gap: 14px;
  min-width: 0;
}

.enroll-manual .disclosure-plain .secret {
  margin-top: 8px;
}

.divider {
  height: 1px;
  margin: 24px 0;
  border: 0;
  background: var(--border);
}

.auth-card .divider + .form,
.auth-card .divider + .callout {
  margin-top: 0;
}

.auth-card .divider + .callout + .form {
  margin-top: 16px;
}

.enroll-grid-single {
  grid-template-columns: minmax(0, 1fr);
}

.enroll-qr {
  display: grid;
  align-content: start;
  margin: 0;
}

/* ---- error page --------------------------------------------------------- */

.error-page {
  max-width: 36rem;
  margin: 64px auto 0;
  text-align: center;
}

.error-icon {
  display: inline-grid;
  place-items: center;
  width: 48px;
  height: 48px;
  margin-bottom: 16px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface);
  box-shadow: var(--shadow-card);
  color: var(--text-muted);
}

.error-icon .callout-icon {
  width: 22px;
  height: 22px;
  margin: 0;
}

.error-page .error-code {
  display: flex;
  width: fit-content;
  margin: 0 auto;
}

.error-code {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
}

.error-title {
  margin-top: 14px;
  font-size: 22px;
  font-weight: 650;
  letter-spacing: -0.01em;
}

.error-detail {
  margin-top: 8px;
  color: var(--text-muted);
}

.error-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 24px;
}

.auth-card .error-page {
  margin-top: 0;
}

.error-facts {
  width: fit-content;
  max-width: 100%;
  margin: 20px auto 0;
  padding: 14px 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius-callout);
  background: var(--surface);
  text-align: left;
}

/* ---- invite result ------------------------------------------------------ */

.invite-card {
  margin-top: 16px;
}

.invite-card .card-body > .callout {
  margin-bottom: 20px;
}

.invite-facts {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
}

/* The deploy console's own layout: the three-card grid, the job log, the
   activity list and the setup steps. Everything else is the hub console's
   stylesheet, copied unchanged. static.go serves this before responsive.css. */

.node-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  margin-bottom: 24px;
}

/* The three cards are one row: each is a column whose body takes the spare
   height, so the domain links and buttons line up along the bottom. */
.node-grid > .card {
  display: flex;
  flex-direction: column;
}

.node-grid > .card > .card-body {
  flex: 1;
}

.node-version {
  margin-bottom: 12px;
  font-size: 24px;
  font-weight: 650;
  letter-spacing: -0.01em;
}

.card-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.log {
  max-height: 32rem;
  margin: 0;
  overflow: auto;
  padding: 16px 20px;
  background: var(--surface-2);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* A running job's log is filled by console.js; until its first text arrives
   there is nothing to show. */
.log:empty {
  display: none;
}

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

.job-list li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 12px;
  padding: 12px 20px;
  border-top: 1px solid var(--border);
}

.job-list li:first-child {
  border-top: 0;
}

.job-mark-ok {
  color: var(--success);
  font-weight: 700;
}

.job-mark-failed {
  color: var(--danger);
  font-weight: 700;
}

.setup-steps {
  margin: 12px 0 16px;
  padding-left: 20px;
}

.setup-steps li {
  margin: 6px 0;
}

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

/* The controls beside a page title: the admins page opens its two forms from
   here. */
.page-actions {
  display: flex;
  flex: none;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

/* A form shown as a modal by console.js. It follows the confirmation dialog
   beside it in components.css; what differs is that this one holds a real
   form, so it is wider and its own submit posts it. */
dialog.modal {
  width: min(30rem, calc(100vw - 32px));
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-dialog);
}

dialog.modal::backdrop {
  background: var(--backdrop);
}

.modal-form {
  margin: 0;
  padding: 22px;
}

.modal-title {
  font-size: 17px;
  font-weight: 600;
  line-height: 1.35;
}

.modal-sub {
  margin-top: -8px;
  color: var(--text-muted);
  font-size: 14px;
}

/* The Windows agent page puts a sha256 and file paths in hints and callouts:
   long runs with no break opportunity, which would otherwise push a card
   wider than a phone. */
.hint,
.callout-content p {
  overflow-wrap: anywhere;
}

/* Narrow-width layouts and reduced motion. Loaded last so it overrides everything above. */

/* ---- responsive --------------------------------------------------------- */

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

  .stats > :last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }
}

@media (max-width: 720px) {
  .enroll-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 20px;
  }

  .qr-panel {
    justify-self: center;
    width: 13.5rem;
  }
}

@media (max-width: 640px) {
  .topbar-inner {
    gap: 12px;
    padding: 0 16px;
  }

  /* Narrow: the brand keeps its mark and name, the breadcrumb keeps only the
     page the operator is on, and Sign out stays. */
  .brand-product,
  .crumbs li:not(:last-child) {
    display: none;
  }

  .crumbs li:last-child::before {
    display: none;
  }

  .page {
    padding: 24px 16px 56px;
  }

  .page-title {
    font-size: 21px;
  }

  .card-header,
  .card-body {
    padding-right: 16px;
    padding-left: 16px;
  }

  .card-footer {
    padding-right: 16px;
    padding-left: 16px;
  }

  .table th,
  .table td {
    padding-right: 12px;
    padding-left: 12px;
  }

  .table th:first-child,
  .table td:first-child {
    padding-left: 16px;
  }

  .table th:last-child,
  .table td:last-child {
    padding-right: 16px;
  }

  .choice-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  /* Tables at phone width: the columns marked optional step aside -- a
     build's branch and registrar; a customer's live-token count (the tile
     above totals it) and chevron; a token's last use; the active table's
     status pill (always "live" there); a token's kind column; the inactive
     table's revoked time (its pill already states it). The active table's
     kind is not lost with its column: it moves to a second line under the
     short id (.token-kind-inline), because which credential to revoke is the
     decision that table exists for. The column
     that holds Assign or Revoke stays pinned to the right edge while the
     rest scrolls under it -- the page's write actions never sit off-screen. */
  .table .col-optional {
    display: none;
  }

  .table .token-kind-inline {
    display: block;
  }

  /* A dashboard row's "newer available" flag drops under its version. */
  .table .cell-inline {
    flex-wrap: wrap;
  }

  .table-fixed {
    min-width: 0;
    table-layout: auto;
  }

  .table-fixed col {
    width: auto;
  }

  .table .col-actions {
    position: sticky;
    right: 0;
    z-index: 1;
    background: var(--surface);
    box-shadow: -10px 0 10px -10px var(--border-strong);
  }

  .table th.col-actions {
    background: var(--surface-2);
  }

  .table tbody tr:hover td.col-actions {
    background: var(--row-hover);
  }

  .auth {
    justify-content: flex-start;
    padding-top: 40px;
  }

  .auth-card {
    padding: 24px 20px;
  }

  .input-search {
    max-width: none;
  }
}

@media (max-width: 480px) {
  .stats {
    grid-template-columns: minmax(0, 1fr);
    gap: 8px;
  }

  .stats > :last-child:nth-child(odd) {
    grid-column: auto;
  }

  /* One column of full-size tiles would push the page's content a screen
     down, so each tile becomes a compact row: label and sub-line on the
     left, the value on the right. */
  .stat {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "label value" "sub value";
    align-items: center;
    column-gap: 16px;
    padding: 12px 16px;
  }

  .stat-label {
    grid-area: label;
  }

  .stat-value {
    grid-area: value;
    min-height: 0;
    margin-top: 0;
    font-size: 24px;
  }

  .stat-value.is-version,
  .stat-value.is-empty {
    font-size: 18px;
  }

  .stat-sub {
    grid-area: sub;
    min-height: 0;
    margin-top: 2px;
    font-size: 12px;
  }

  .facts {
    grid-template-columns: minmax(0, 1fr);
    gap: 2px;
  }

  .facts dd + dt {
    margin-top: 10px;
  }
}

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

