:root {
  --bg: #0f1115;
  --panel: #171a21;
  --panel-2: #1e222b;
  --panel-3: #252a35;
  --line: #2a2f3a;
  --line-soft: #21262f;
  --ink: #e8eaef;
  --dim: #969db0;
  --faint: #6b7385;
  --accent: #7cc4ff;
  --violet: #b39bf5;
  --ok: #5bd18b;
  --warn: #e8b463;
  --bad: #f0736a;
  --busy: #7cc4ff;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --r: 12px;
}

* { box-sizing: border-box; }

/* The browser's own `[hidden] { display: none }` has the same specificity as a class
   selector and loses to every rule below that sets `display`. That is why the "wartet
   auf Antwort"-Leiste, the run bar and the "online"-Kachelbadge were on every page all
   the time regardless of what the JavaScript said. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background:
    radial-gradient(1200px 600px at 15% -10%, #1b2130 0%, transparent 60%),
    radial-gradient(900px 500px at 95% 0%, #1a1c2a 0%, transparent 55%),
    var(--bg);
  background-attachment: fixed;
  color: var(--ink);
  font: 15px/1.55 system-ui, -apple-system, "Segoe UI", sans-serif;
}

main { max-width: 1500px; margin: 0 auto; padding: 20px 18px 80px; }
.spacer { flex: 1; }
.mono { font-family: var(--mono); }
.small { font-size: 12px; }
.num { text-align: right; font-variant-numeric: tabular-nums; }
.tnum { font-variant-numeric: tabular-nums; }

/* ── top bar ─────────────────────────────────────────────────────────────
   Two rows: identity and connection above, the meters below. The meters are
   the reason this bar exists — a long run is mostly a question of what it is
   consuming, and that used to be visible nowhere. */
.topbar {
  position: sticky; top: 0; z-index: 30;
  background: color-mix(in srgb, var(--panel) 92%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}
.topbar-row { display: flex; align-items: center; gap: 12px; padding: 10px 18px; }
.topbar-row + .topbar-row { border-top: 1px solid var(--line-soft); padding-top: 8px; padding-bottom: 8px; }
.brand { color: var(--ink); text-decoration: none; font-weight: 650; letter-spacing: .2px; display: flex; gap: 8px; align-items: center; }
.brand b { font-weight: 650; }
.brand svg { opacity: .85; }
.billing { color: var(--dim); font-size: 12px; }
.conn {
  font-size: 11px; padding: 2px 9px; border-radius: 99px;
  border: 1px solid var(--line); color: var(--faint);
}
.conn.live { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 40%, transparent); }
.conn.live::before { content: "● "; }

/* meters */
.meters { display: flex; gap: 10px; flex-wrap: wrap; align-items: stretch; width: 100%; }
.meter {
  display: flex; flex-direction: column; gap: 3px;
  padding: 5px 12px 6px; min-width: 128px;
  border: 1px solid var(--line-soft); border-radius: 9px;
  background: color-mix(in srgb, var(--panel-2) 60%, transparent);
}
.meter-k { font-size: 9.5px; text-transform: uppercase; letter-spacing: .7px; color: var(--faint); }
.meter-v { font-size: 14px; font-variant-numeric: tabular-nums; line-height: 1.2; }
.meter-v small { color: var(--faint); font-size: 11px; font-weight: 400; }
.bar { height: 3px; border-radius: 99px; background: var(--panel-3); overflow: hidden; margin-top: 3px; }
.bar > i { display: block; height: 100%; background: var(--accent); border-radius: 99px; transition: width .4s ease; }
.bar.warn > i { background: var(--warn); }
.bar.bad > i { background: var(--bad); }
.meter.unknown .meter-v { color: var(--faint); font-size: 12px; }

/* ── cards ───────────────────────────────────────────────────────────── */
.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 16px;
  margin-bottom: 16px;
}
.card > h2 {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 12px; font-size: 12px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .7px; color: var(--dim);
}
.card > h2 .badge {
  font-size: 10px; letter-spacing: .4px; color: var(--faint);
  border: 1px solid var(--line); border-radius: 99px; padding: 1px 7px; text-transform: none;
}

/* ── compose ─────────────────────────────────────────────────────────── */

/* `input:not([type=checkbox])` statt einer Liste der erlaubten Typen. Die Liste hier war
   `number, text` — und als das Anmeldeformular dazukam, erbten `email` und `password`
   die Vorgabe des Browsers: schwarze Schrift auf schwarzem Grund, unsichtbar bis zum
   ersten Tastendruck. Eine Aufzählung, die jeden neuen Feldtyp stillschweigend ausschließt,
   ist der falsche Weg herum; ausgenommen wird, was anders aussehen *soll*. */
textarea, input:not([type=checkbox]), select {
  width: 100%; background: var(--bg); color: var(--ink);
  border: 1px solid var(--line); border-radius: 9px; padding: 10px 12px;
  font: inherit; resize: vertical;
}
/* Der Cursor ist ein eigenes Attribut und erbt `color` nicht überall. */
textarea, input:not([type=checkbox]) { caret-color: var(--ink); }

/* Ausgefüllt vom Passwortmanager sieht anders aus als selbst getippt: Chrome setzt
   eigenen Grund und eigene Schriftfarbe und lässt sich bei der Fläche nicht über
   `background` umstimmen — ein sehr großer innerer Schatten ist der einzige Weg. Ohne
   das ist ein automatisch ausgefülltes Feld hellblau mit schwarzer Schrift, also genau
   der Fehler von oben, nur ausgelöst vom Browser statt vom CSS. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--ink);
  caret-color: var(--ink);
  box-shadow: 0 0 0 1000px var(--bg) inset;
  /* Die Einfärbung passiert per Übergang; ihn ins Unendliche zu schieben ist der
     verbreitete Weg, ihn nie ankommen zu lassen. */
  transition: background-color 5000s ease-in-out 0s;
}
textarea:focus, input:focus, select:focus {
  outline: 2px solid color-mix(in srgb, var(--accent) 50%, transparent); outline-offset: -1px;
}
.compose textarea { min-height: 84px; }
.compose-row { display: flex; align-items: center; gap: 12px; margin-top: 12px; flex-wrap: wrap; }
.field { display: flex; flex-direction: column; gap: 4px; }
.field > span { font-size: 10px; text-transform: uppercase; letter-spacing: .6px; color: var(--faint); }
.field select, .field input { padding: 7px 10px; font-size: 13px; }
.field.w-model select { min-width: 140px; }
.field.w-num input { width: 96px; }
/* A limit's checkbox rides in its own label, so the whole field toggles on click.
   `normal-case` on the span because "Budget $" and "Konto-Limit" read badly shouted. */
.field.limit > span { display: flex; align-items: center; gap: 5px; text-transform: none; font-size: 11px; }
.field.limit > span input[type=checkbox] { width: auto; padding: 0; margin: 0; accent-color: var(--accent, currentColor); }
/* Switched off is greyed, not hidden: the number stays readable, so turning the limit
   back on shows what it will be rather than an empty box. */
.field.limit.off > span { opacity: .5; }
.field.limit.off input[type=number] { opacity: .4; }
.hint { color: var(--faint); font-size: 11.5px; margin: 6px 0 0; }

button {
  background: var(--accent); color: #0b1016; border: 0;
  border-radius: 9px; padding: 9px 20px; font: inherit; font-weight: 650; cursor: pointer;
}
button:hover { filter: brightness(1.08); }
button:disabled { opacity: .5; cursor: default; }
button.ghost, a.ghost {
  background: none; color: var(--dim); border: 1px solid var(--line);
  padding: 4px 11px; font-weight: 500; font-size: 12px; text-decoration: none; border-radius: 8px;
}
button.ghost:hover, a.ghost:hover { color: var(--ink); border-color: var(--faint); }
button.danger { background: var(--bad); color: #180a09; }
#abort { background: none; border: 1px solid var(--bad); color: var(--bad); }
#delete:hover { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 45%, transparent); }

/* ── confirmation ────────────────────────────────────────────────────────
   Deleting is the only irreversible thing this UI can do, so it is the only
   thing that asks. <dialog> brings the backdrop, the focus trap and Escape. */
dialog.confirm {
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r);
  padding: 18px 20px; max-width: 400px;
  box-shadow: 0 24px 60px rgba(0,0,0,.55);
}
dialog.confirm::backdrop { background: rgba(9, 11, 15, .62); }
dialog.confirm h3 { margin: 0; font-size: 15px; }
dialog.confirm p { margin: 8px 0 0; font-size: 13px; color: var(--dim); }
/* Das Tippfeld einer unwiderruflichen Bestätigung. Es steht zwischen Frage und Knöpfen,
   weil es der Schritt dazwischen ist — und der Knopf bleibt tot, bis es stimmt. */
.confirm-type { display: flex; flex-direction: column; gap: 6px; margin-top: 16px; }
.confirm-type span { font-size: 11px; color: var(--faint); }
.confirm-type input {
  font-family: var(--mono); font-size: 13px; letter-spacing: .06em;
  padding: 8px 11px; border-radius: 8px;
}
.confirm-row { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }
.confirm-row button:disabled { opacity: .35; }
.confirm-row button { padding: 6px 14px; font-size: 12.5px; }

.err { color: var(--bad); margin: 10px 0 0; }
.empty { color: var(--faint); font-size: 13px; margin: 4px 0 0; }

/* ── overview tiles ──────────────────────────────────────────────────────
   A table of thirteen rows and seven columns answered "what is in here" badly:
   the two things actually looked for — is it finished, and is it running — were
   a dot in the first column and nowhere at all. A tile has room to say both and
   to carry its own controls. */
.tiles {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
.tile {
  position: relative; display: flex; flex-direction: column; gap: 6px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r); padding: 10px 12px;
  transition: border-color .15s, transform .15s, box-shadow .15s;
}
.tile:hover { border-color: var(--faint); transform: translateY(-1px); box-shadow: 0 8px 22px rgba(0,0,0,.28); }
.tile.live { border-color: color-mix(in srgb, var(--ok) 45%, transparent); }

.tile-top { display: flex; align-items: center; gap: 8px; font-size: 11px; }
.tile-state { color: var(--dim); }
.tile-id { color: var(--faint); font-size: 11px; }
/* Above the stretched link, or the tile's own anchor swallows the click. */
.tile-del, .tile-dl {
  position: relative; z-index: 1;
  padding: 2px 7px; font-size: 12px; line-height: 1.5;
}
.tile-dl { text-decoration: none; }
.tile-dl:hover { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.tile-del:hover { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 45%, transparent); }
.tile-round {
  color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius: 99px; padding: 0 7px; font-size: 10px;
}
/* Wer den Auftrag gegeben hat. Zurückhaltend: solange alle alles sehen, ist es eine
   Herkunftsangabe und keine Zugangsangabe — und die Kachel gehört dem Titel. */
.tile-owner {
  color: var(--faint); font-size: 10.5px; letter-spacing: .02em;
  max-width: 11ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.online {
  display: inline-flex; align-items: center; gap: 5px;
  color: var(--ok); font-weight: 600; letter-spacing: .3px;
}
.online::before {
  content: ""; width: 6px; height: 6px; border-radius: 99px;
  background: var(--ok); animation: pulse 1.4s ease-in-out infinite;
}

/* The stretched link: the whole tile is clickable, and the buttons below lift
   themselves above it rather than being nested inside an anchor — a button
   inside a link is neither reliably clickable nor valid. */
.tile-title {
  color: var(--ink); text-decoration: none; font-size: 13.5px; line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.tile-title::after { content: ""; position: absolute; inset: 0; border-radius: var(--r); }
.tile:hover .tile-title { color: var(--accent); }

.tile-note {
  margin: 0; font-size: 11.5px; color: var(--warn);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tile-note.bad { color: var(--bad); }

.tile-stats {
  display: flex; gap: 11px; flex-wrap: wrap; align-items: baseline;
  font-size: 10.5px; color: var(--faint);
}
.tile-stats b { font-weight: 500; font-size: 11.5px; color: var(--dim); }

.tile-run {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin-top: auto; padding-top: 7px; border-top: 1px solid var(--line-soft);
  position: relative; z-index: 1;   /* above the stretched link */
}
.tile-run button, .tile-run a { padding: 4px 10px; font-size: 11.5px; }
.tile-run .run-stop { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 40%, transparent); }
.tile-run .run-open { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 40%, transparent); }
.tile-run .run-note {
  font-size: 10.5px; color: var(--faint); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; max-width: 45%;
}
.tile-run .run-note.busy { color: var(--warn); }

/* ── job table ───────────────────────────────────────────────────────── */
  text-align: left; font-size: 10.5px; text-transform: uppercase; letter-spacing: .6px;
  color: var(--faint); font-weight: 500; padding: 0 10px 8px; border-bottom: 1px solid var(--line);
}
.state { font-size: 12px; color: var(--dim); }
td.dot, .dot { width: 18px; }
.dot > span { display: inline-block; width: 9px; height: 9px; border-radius: 99px; background: var(--faint); }
.s-running, .s-planning, .s-verifying, .s-repairing, .s-wrapping_up { background: var(--busy); animation: pulse 1.4s ease-in-out infinite; }
.s-queued { background: var(--faint); }
.s-waiting_human, .s-awaiting_scope { background: var(--warn); animation: pulse 1s ease-in-out infinite; }
.s-done { background: var(--ok); }
.s-cut_short { background: var(--warn); }
.s-failed, .s-budget_exceeded { background: var(--bad); }
.s-aborted { background: var(--faint); }
@keyframes pulse { 50% { opacity: .3; } }
/* ── job head ────────────────────────────────────────────────────────── */
.jobhead-top { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.jobhead h1 { font-size: 17px; margin: 0; }
.prompt {
  color: var(--dim); margin: 12px 0 0; white-space: pre-wrap;
  max-height: 4.7em; overflow: hidden; position: relative; cursor: pointer;
}
.prompt.open { max-height: none; }
.prompt:not(.open)::after {
  content: ""; position: absolute; inset: auto 0 0 0; height: 1.6em;
  background: linear-gradient(transparent, var(--panel));
}
.meta { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 0; }
.meta .chip {
  display: inline-flex; gap: 6px; align-items: baseline;
  border: 1px solid var(--line-soft); border-radius: 8px; padding: 4px 10px;
  background: var(--panel-2); font-size: 12px; color: var(--dim);
}
.meta .chip b { color: var(--ink); font-weight: 550; font-variant-numeric: tabular-nums; }
.meta .chip .k { font-size: 10px; text-transform: uppercase; letter-spacing: .6px; color: var(--faint); }
.result {
  margin: 14px 0 0; padding: 12px 14px; background: var(--panel-2);
  border-left: 2px solid var(--ok); border-radius: 0 8px 8px 0; white-space: pre-wrap;
}
.banner {
  margin: 14px 0 0; padding: 10px 14px; border-radius: 8px; font-size: 13.5px;
  background: color-mix(in srgb, var(--warn) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--warn) 35%, transparent); color: var(--warn);
}
.banner.bad {
  background: color-mix(in srgb, var(--bad) 12%, transparent);
  border-color: color-mix(in srgb, var(--bad) 35%, transparent); color: var(--bad);
}

/* ── board ───────────────────────────────────────────────────────────────
   Trace on the left, files and preview stacked on the right. The trace is the
   tall column because it is the thing that grows; the right side is a fixed
   pair of panels that stay where the eye left them. */
.board { display: grid; grid-template-columns: minmax(0, 1fr) 420px; gap: 16px; align-items: start; }
.board > .col { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.board .sticky { position: sticky; top: 108px; }
@media (max-width: 1150px) { .board { grid-template-columns: 1fr; } .board .sticky { position: static; } }

/* ── what it is doing right now ───────────────────────────────────────────
   One line, replaced in place. The trace that used to live here was a chat log
   of two hundred steps: it answered "what happened at 14:31", which nobody
   asked, and buried "what is it doing" and "what came out of it", which are
   the only two questions this page exists for. */
.now-row { display: flex; gap: 11px; align-items: center; }
.now-ico {
  flex: none; width: 34px; height: 34px; border-radius: 10px; display: grid; place-items: center;
  font-size: 16px; background: var(--panel-2); border: 1px solid var(--line-soft);
}
.now.busy .now-ico { animation: pulse 1.6s ease-in-out infinite; border-color: var(--busy); }
.now-txt { flex: 1; min-width: 0; }
.now-what {
  font-family: var(--mono); font-size: 13px; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.now-sub {
  font-size: 11.5px; color: var(--faint); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.now-sub.ok { color: var(--ok); }
.now-sub.bad { color: var(--bad); }
.now-t { flex: none; color: var(--faint); font-size: 10.5px; }
/* The last thing the agent said in prose — one paragraph, folded until clicked. */
.now-say {
  margin: 11px 0 0; padding: 9px 12px; border-radius: 9px;
  border-left: 2px solid var(--accent); background: var(--panel-2);
  font-size: 12.5px; line-height: 1.55; color: var(--dim); white-space: pre-wrap;
}
.now-say.clamped { max-height: 96px; overflow: hidden; cursor: zoom-in; mask-image: linear-gradient(#000 60%, transparent); }
.now-say:not(.clamped) { cursor: zoom-out; }

/* ── the facts, as tiles ──────────────────────────────────────────────── */
.facts {
  display: grid; gap: 7px; margin: 14px 0 0;
  grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
}
.fact {
  background: var(--panel-2); border: 1px solid var(--line-soft); border-radius: 9px;
  padding: 7px 9px; display: flex; flex-direction: column; gap: 1px; min-width: 0;
}
.fact .k { font-size: 9.5px; text-transform: uppercase; letter-spacing: .6px; color: var(--faint); }
.fact b {
  font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Carries the round's share under the project's total, so it has to stay one line. */
.fact small {
  font-size: 10.5px; color: var(--faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── files ───────────────────────────────────────────────────────────── */
.tree { list-style: none; margin: 0; padding: 0; max-height: 62vh; overflow: auto; scrollbar-width: thin; }
.tree ul { list-style: none; margin: 0; padding-left: 13px; border-left: 1px solid var(--line-soft); }
.tree li { position: relative; }
.row {
  display: flex; width: 100%; gap: 7px; align-items: center;
  background: none; border: 0; padding: 4px 6px; color: var(--ink);
  font: inherit; font-size: 12.5px; text-align: left; cursor: pointer; border-radius: 6px;
}
.row:hover { background: var(--panel-2); }
/* The row and its ⭳ are siblings: an anchor nested in a button is not a link the
   browser will download from, and the row is a button. */
.rowline { display: flex; align-items: center; gap: 2px; }
.rowline .row { flex: 1 1 auto; width: auto; min-width: 0; }
.dl {
  flex: none; padding: 3px 5px; border-radius: 6px; line-height: 1;
  font-size: 12px; color: var(--faint); text-decoration: none;
  opacity: .3; transition: opacity .12s, color .12s;
}
.rowline:hover .dl { opacity: 1; }
.dl:hover, .dl:focus-visible { opacity: 1; color: var(--accent); background: var(--panel-2); }
.row.active { background: color-mix(in srgb, var(--accent) 15%, transparent); color: var(--accent); }
.row .nm { font-family: var(--mono); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row .sz { margin-left: auto; color: var(--faint); font-size: 10.5px; flex: none; font-variant-numeric: tabular-nums; }
.row .tw { flex: none; width: 12px; color: var(--faint); font-size: 9px; transition: transform .12s; }
.row.open .tw { transform: rotate(90deg); }
.row .ico { flex: none; width: 15px; text-align: center; font-size: 11px; }
.row.dir .nm { color: var(--ink); font-weight: 550; }
.row.dir .ico { color: var(--accent); }
li.collapsed > ul { display: none; }

/* What this round did to each file. The colour answers it before a number is
   read: new is green, gone is red, touched carries its +/-. */
.row.new { background: color-mix(in srgb, var(--ok) 9%, transparent); }
.row.new:hover { background: color-mix(in srgb, var(--ok) 16%, transparent); }
.row.changed { background: color-mix(in srgb, var(--accent) 7%, transparent); }
.row.changed:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.row.deleted { background: color-mix(in srgb, var(--bad) 10%, transparent); cursor: default; opacity: 1; }
.row.deleted .nm { color: var(--faint); text-decoration: line-through; }
.row.deleted .ico { color: var(--bad); }
.row .sz > span + span { margin-left: 5px; }
.plus { color: var(--ok); }
.minus { color: var(--bad); }
.filesum {
  display: flex; align-items: center; gap: 6px; margin: 0 0 10px;
  font-size: 11.5px; color: var(--dim); font-variant-numeric: tabular-nums;
}
.entrybar {
  display: flex; gap: 8px; align-items: center; margin-bottom: 10px; padding: 8px 10px;
  border-radius: 9px; font-size: 12.5px;
  background: color-mix(in srgb, var(--ok) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--ok) 30%, transparent);
}
.entrybar .nm { font-family: var(--mono); color: var(--ok); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.entrybar button { padding: 4px 12px; font-size: 12px; }

/* ── preview ─────────────────────────────────────────────────────────── */
#preview-body iframe { width: 100%; height: 56vh; border: 1px solid var(--line); border-radius: 9px; background: #fff; }
#preview-body img { max-width: 100%; border-radius: 9px; background: #fff; }
#preview-body pre {
  margin: 0; padding: 12px; background: var(--bg); border: 1px solid var(--line);
  border-radius: 9px; overflow: auto; max-height: 56vh; font-size: 12px; color: var(--ink);
}

/* ── question dialog ─────────────────────────────────────────────────────
   The agent's own dialog, not the browser's: `prompt()` gives no options, no
   context, and blocks the page it is asking about. */
.ask-back {
  position: fixed; inset: 0; z-index: 100; display: grid; place-items: center;
  padding: 14px; overflow-y: auto;
  background: rgba(6, 8, 12, .72); backdrop-filter: blur(4px);
  animation: fade .18s ease;
}
@keyframes fade { from { opacity: 0; } }
/* Scrolls inside itself rather than off the screen: a question with context and
   four options was taller than a phone, and the centred box put its buttons past
   the bottom edge with nothing to scroll. */
.ask {
  width: min(600px, 100%); max-height: calc(100dvh - 28px); overflow-y: auto;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 16px; padding: 18px; box-shadow: 0 30px 80px rgba(0,0,0,.7);
  animation: rise .22s cubic-bezier(.2,.9,.3,1);
}
@keyframes rise { from { transform: translateY(14px) scale(.98); opacity: 0; } }
.ask .who { display: flex; align-items: center; gap: 8px; color: var(--warn); font-size: 11px; text-transform: uppercase; letter-spacing: .8px; }
.ask h3 { margin: 12px 0 0; font-size: 18px; line-height: 1.4; font-weight: 600; }
.ask .ctx { color: var(--dim); font-size: 13px; margin: 10px 0 0; white-space: pre-wrap; }
.ask .opts { display: flex; flex-direction: column; gap: 8px; margin: 16px 0 0; }
.ask .opts button {
  background: var(--panel-2); color: var(--ink); border: 1px solid var(--line);
  text-align: left; font-weight: 500; padding: 11px 14px; border-radius: 10px;
}
.ask .opts button:hover { border-color: var(--accent); background: var(--panel-3); }
.ask .free { display: flex; gap: 8px; margin: 14px 0 0; }
.ask .free input { flex: 1; }
.ask .age { color: var(--faint); font-size: 11.5px; margin: 14px 0 0; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ask .age .why { flex: 1; min-width: 120px; }
.ask .err { font-size: 12.5px; }

/* ── the other three request shapes ── */

.ask .setup { color: var(--accent); word-break: break-all; }
.ask .steps { color: var(--dim); font-size: 13px; margin: 10px 0 0; padding-left: 20px; }
.ask .steps li { margin: 4px 0; }
.ask .remember { display: flex; align-items: center; gap: 7px; margin: 10px 0 0; color: var(--dim); font-size: 12.5px; }
.ask .remember input { width: auto; }

/* The command is meant to be copied verbatim, so it wraps rather than scrolls: a line
   cut off at the edge is a line someone pastes half of. */
.ask .cmd { display: flex; align-items: flex-start; gap: 8px; margin: 14px 0 0; }
.ask .cmd code {
  flex: 1; background: var(--panel-3); border: 1px solid var(--line); border-radius: 8px;
  padding: 10px 12px; font-size: 12.5px; white-space: pre-wrap; word-break: break-all;
}

.ask .drop {
  margin: 14px 0 0; padding: 26px 14px; text-align: center; cursor: pointer;
  border: 1px dashed var(--line); border-radius: 10px; color: var(--dim); font-size: 13px;
}
.ask .drop:hover, .ask .drop.over { border-color: var(--accent); color: var(--fg); background: var(--panel-3); }

/* a question that is open but not in the way */
.askbar {
  display: flex; align-items: center; gap: 10px; margin-bottom: 16px;
  padding: 10px 14px; border-radius: 10px; cursor: pointer;
  background: color-mix(in srgb, var(--warn) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent); color: var(--warn);
}
.askbar:hover { filter: brightness(1.15); }

/* ── running the project ─────────────────────────────────────────────────
   Sits above the file tree, because once a project can be started, starting
   it is what you came for — reading its files is the fallback. */
.runbar {
  margin-bottom: 12px; padding: 10px 12px; border-radius: 10px;
  background: color-mix(in srgb, var(--accent) 8%, var(--panel-2));
  border: 1px solid color-mix(in srgb, var(--accent) 28%, transparent);
}
.runbar.live {
  background: color-mix(in srgb, var(--ok) 9%, var(--panel-2));
  border-color: color-mix(in srgb, var(--ok) 36%, transparent);
}
.runbar.bad { background: color-mix(in srgb, var(--bad) 9%, var(--panel-2));
              border-color: color-mix(in srgb, var(--bad) 34%, transparent); }
.runbar-top { display: flex; align-items: center; gap: 10px; }
.runbar .runico { flex: none; color: var(--accent); font-size: 13px; }
.runbar.live .runico { color: var(--ok); animation: pulse 1.6s ease-in-out infinite; }
.runbar .runtxt { min-width: 0; display: flex; flex-direction: column; }
.runbar .runtxt b { font-size: 13px; font-weight: 600; }
.runbar .runsub {
  font-size: 11px; color: var(--faint); font-family: var(--mono);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.runbar button { padding: 5px 14px; font-size: 12px; }
.runnet {
  display: flex; align-items: center; gap: 7px; margin-top: 8px;
  font-size: 11.5px; color: var(--dim); cursor: pointer;
}
.runnet input { width: auto; }
.runlinks { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 9px; }
.runlinks a {
  font-family: var(--mono); font-size: 12px; text-decoration: none;
  color: var(--ok); border: 1px solid color-mix(in srgb, var(--ok) 40%, transparent);
  border-radius: 7px; padding: 3px 10px;
}
.runlinks a:hover { background: color-mix(in srgb, var(--ok) 14%, transparent); }
.runlinks a.open-here { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.runfoot { display: flex; align-items: center; gap: 8px; margin-top: 9px; }
.runcount { font-size: 11.5px; color: var(--dim); font-variant-numeric: tabular-nums; }
.runcount.warn { color: var(--warn); }
.runlog {
  margin: 9px 0 0; padding: 9px 11px; max-height: 220px; overflow: auto;
  background: #0b0d12; border: 1px solid var(--line); border-radius: 8px;
  font-family: var(--mono); font-size: 11px; color: var(--dim);
  white-space: pre-wrap; overflow-wrap: anywhere;
}

/* ── another round ───────────────────────────────────────────────────── */
.followup { margin-top: 14px; }
.followup .fu-open { padding: 6px 14px; }
.followup form { margin-top: 10px; }
.followup textarea { min-height: 70px; }

/* ── narrow screens ───────────────────────────────────────────────────────
   The trace hangs cards off both sides of a spine. On a phone that leaves each
   card about 140px wide, which is narrower than the paths written in them — so
   below this width the spine moves to the left edge and everything hangs off
   one side. The shape survives; only the symmetry goes. */
@media (max-width: 760px) {
  main { padding: 14px 12px 60px; }
  .card { padding: 13px; border-radius: 10px; }

  .trace::before { left: 9px; }
  .node, .node.left, .node.right {
    width: auto; margin-left: 26px; margin-right: 0;
  }
  .node.left::before, .node.right::before { left: -17px; right: auto; }
  .node.left::after, .node.right::after { left: -21px; right: auto; }
  .node.wide { margin-left: 0; }
  /* The bubble's tail always points back at the spine, which is now always left. */
  .node.left .bubble::after {
    left: -5px; right: auto;
    border-right: 0; border-top: 0; border-left: inherit; border-bottom: inherit;
  }

  .jobhead h1 { font-size: 15px; }
  .prompt { max-height: 6.4em; }
  .meta { gap: 6px; }
  .meta .chip { padding: 3px 8px; font-size: 11.5px; }

  /* One tile per row: two columns of 150px would clip every title. */
  .tiles { grid-template-columns: 1fr; gap: 11px; }
  .tile { padding: 12px; }
  .tile-stats { gap: 13px; }
  .tile-run { padding-top: 9px; }

  .compose-row { gap: 9px; }
  .field.w-num input { width: 74px; }
  .runbar-top { flex-wrap: wrap; }
  .runbar .runtxt { flex: 1 1 100%; order: -1; }
  #preview-body iframe, #preview-body pre { height: 62vh; max-height: 62vh; }
  .ask { padding: 15px; }
  .ask h3 { font-size: 16px; }
  .facts { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); }
}

/* Touch input has no hover, and a 4px row is not a target a thumb can hit. */
@media (pointer: coarse) {
  .row { padding: 9px 8px; }
  .row .tw { width: 16px; font-size: 11px; }
  button, a.ghost { min-height: 38px; }
  button.ghost, a.ghost { padding: 8px 13px; }
  .ask .opts button { padding: 13px 14px; }
  /* Hover styling on touch sticks after a tap and reads as a stuck selection. */
  .row:hover { background: none; }
  .row.active { background: color-mix(in srgb, var(--accent) 15%, transparent); }
  /* A ⭳ that only appears on hover never appears at all on a phone. */
  .dl { opacity: .75; padding: 9px 8px; min-width: 34px; text-align: center; }
  .rowline:hover .dl, .dl:hover { opacity: .75; background: none; color: var(--faint); }
}

/* iOS zooms the page in when a focused input is under 16px. */
@media (max-width: 760px) {
  textarea, input:not([type=checkbox]), select { font-size: 16px; }
}


/* ══ Die Türseiten ═══════════════════════════════════════════════════════════
   Anmelden, Registrieren, Konto, Verwaltung. Das sind die einzigen Seiten dieses
   Dienstes, die jemand sieht, bevor er etwas von ihm hat — und die einzigen, auf denen
   nichts zu tun ist außer einer Sache. Deshalb dürfen sie das, was die Arbeitsflächen
   nicht dürfen: viel Platz und ein großes leuchtendes Ding.

   Ein Ring, kein Farbverlauf über alles. Der Ring ist das Zeichen dieses Dienstes — ein
   Lauf, der herumgeht und zurückkommt — und er lässt die Mitte dunkel, wo die Karte
   steht. Zwei Farben, nicht fünf: das Violett, das die Oberfläche schon führt, und eine
   warme Glut dagegen. Alles davon ist CSS, kein Bild, keine Schrift von außen: diese
   Seite ist das Erste, was ein Browser hier lädt, und das Erste soll nicht auf ein
   Netzwerk warten. */

:root {
  --ember: #ff9057;
  /* Zwei Farben, nicht fünf. Das Violett führt die Oberfläche ohnehin schon; die Glut
     steht dagegen. Kräftiger angesetzt, als es aussieht: was hier steht, geht durch
     einen 34-px-Weichzeichner, und ein Weichzeichner frisst Sättigung. */
  --glow-1: color-mix(in oklab, var(--violet) 78%, transparent);
  --glow-2: color-mix(in oklab, var(--ember) 72%, transparent);
}

body.lit {
  /* Tiefer als der Rest der Oberfläche. Ein Leuchten braucht etwas, worin es leuchtet. */
  background: #07080b;
  min-height: 100dvh;
}

/* Die Karte steht in der dunklen Mitte des Rings, nicht darüber. Deshalb wird der
   Hauptbereich zentriert statt oben angesetzt — sonst liegt das Licht hinter dem Text. */
body.lit main {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  min-height: calc(100dvh - 58px);
  padding-top: 0;
}

/* Alle drei Lagen liegen hinter allem, fangen keine Klicks und stehen beim Scrollen
   still — ein mitfahrendes Leuchten sieht aus wie ein Fehler. */
.aurora {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}

.aurora::before,
.aurora::after {
  content: "";
  position: absolute;
  left: 50%;
  top: calc(50% + 20px);
  width: min(940px, 94vw);
  aspect-ratio: 1;
  border-radius: 50%;
  transform: translate(-50%, -50%);
}

/* Der weiche Schein. `conic` statt einer gleichmäßigen Farbe, weil ein beleuchteter
   Gegenstand ungleich beleuchtet ist: kalt oben, warm unten, dazwischen der Übergang. */
.aurora::before {
  background: conic-gradient(from 205deg,
    var(--glow-2) 0deg,
    var(--glow-1) 95deg,
    var(--glow-1) 175deg,
    var(--glow-2) 285deg,
    var(--glow-2) 360deg);
  /* Die Mitte herausnehmen: übrig bleibt der Reif. Das Band ist schmal — breit gezogen
     wird daraus eine Vignette, und eine Vignette ist kein Gegenstand. */
  /* Das Loch muss die Karte aufnehmen können. Ist es kleiner, liegt die Karte auf dem
     Ring statt darin — und aus einem Gegenstand mit Tiefe wird ein Aufkleber. */
  mask: radial-gradient(circle at center, transparent 41%, #000 48%, #000 56%, transparent 69%);
  filter: blur(38px);
  opacity: .8;
  animation: ring-turn 72s linear infinite;
}

/* Die scharfe Kante darauf — Exovias eigentliches Zeichen. Ein Haarstrich, kaum
   weichgezeichnet, sonst verschwindet er im Schein darunter. */
.aurora::after {
  background: conic-gradient(from 205deg,
    color-mix(in oklab, var(--ember) 95%, transparent) 0deg,
    color-mix(in oklab, var(--violet) 80%, transparent) 130deg,
    color-mix(in oklab, var(--violet) 45%, transparent) 210deg,
    color-mix(in oklab, var(--ember) 85%, transparent) 310deg,
    color-mix(in oklab, var(--ember) 95%, transparent) 360deg);
  /* Ein Haarstrich. Fällt er unter einen Pixel, zeichnet ihn der Browser gestrichelt. */
  mask: radial-gradient(circle at center, transparent calc(50% - 1.6px), #000 calc(50% - 1.2px), #000 calc(50% - 0.2px), transparent 50%);
  filter: blur(.3px);
  opacity: .9;
  animation: ring-turn 72s linear infinite;
}

/* Die Glut von unten. Sie füllt den unteren Bildrand, den der Ring offen lässt, und ist
   die einzige Lage, die bis an die Kante läuft. */
.aurora > i {
  position: absolute;
  left: 50%;
  bottom: -40vh;
  width: min(1800px, 160vw);
  height: 66vh;
  transform: translateX(-50%);
  background: radial-gradient(50% 50% at 50% 50%, var(--glow-2), transparent 72%);
  filter: blur(70px);
  /* Ein Hauch, kein zweiter Gegenstand. Kräftiger gesetzt wird daraus ein Fleck neben
     dem Ring, und zwei leuchtende Dinge sind eines zu viel. */
  opacity: .26;
}

@keyframes ring-turn { to { transform: translate(-50%, -50%) rotate(1turn); } }

/* Eine Drehung, die niemand angefordert hat, ist für manche Menschen keine Zierde,
   sondern ein Grund, die Seite zu schließen. */
@media (prefers-reduced-motion: reduce) {
  .aurora::before, .aurora::after { animation: none; }
}

body.lit .topbar {
  /* Über dem Licht, nicht davor: keine Fläche, keine Kante. */
  background: none;
  backdrop-filter: none;
  border-bottom: none;
  position: relative;
  z-index: 1;
}

/* Breiter als die Karte, weil die Verwaltung eine Tabelle ist: vier Spalten in 980 px
   bedeuten drei Zeilenumbrüche pro Zeile, und eine Zeile ist hier ein Mensch. Die
   Türseiten stört es nicht — ihre Karte ist ohnehin auf 452 px begrenzt und zentriert. */
main.narrow { max-width: 1160px; }

/* ── die Karte ─────────────────────────────────────────────────────────────── */

.card.auth {
  width: 100%;
  max-width: 452px;
  margin: 0 auto;
  padding: 36px 34px 32px;
  border-radius: 20px;
  /* Glas über dem Leuchten: die Karte steht darin, statt es zu verdecken. */
  /* Glas, nicht Blech: der Ring scheint durch, sonst ist die Karte ein schwarzes Loch
     in einem leuchtenden Reif. */
  background: color-mix(in srgb, var(--panel) 58%, transparent);
  backdrop-filter: blur(26px) saturate(1.25);
  border: 1px solid color-mix(in srgb, #fff 9%, transparent);
  box-shadow:
    0 1px 0 color-mix(in srgb, #fff 8%, transparent) inset,
    0 30px 80px -20px #000;
}

.eyebrow {
  margin: 0 0 14px;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--faint);
}

.card.auth h1 {
  /* Groß und eng. Der Unterschied zwischen „eine Überschrift" und „das Wort, um das es
     geht", ist fast nur der Zeilenabstand und das Tracking. */
  margin: 0 0 8px;
  font-size: clamp(29px, 5vw, 38px);
  font-weight: 640;
  line-height: 1.08;
  letter-spacing: -.024em;
}

.card.auth > p.lead { margin: 0 0 22px; color: var(--dim); font-size: 13.5px; line-height: 1.55; }

.card.auth h2 {
  font-size: 10px; text-transform: uppercase; letter-spacing: .18em; color: var(--faint);
  margin: 30px 0 14px; padding-top: 20px;
  border-top: 1px solid color-mix(in srgb, #fff 7%, transparent);
}

.card.auth form { display: flex; flex-direction: column; gap: 14px; }
.card.auth p { margin: 16px 0 0; }
.card.auth a { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--faint); }
.card.auth a:hover { border-bottom-color: var(--ember); }

/* Felder: ruhiger als im Arbeitsbereich, und der Fokus ist warm statt blau — er ist hier
   das einzige Farbige, das auf eine Handlung zeigt. */
.card.auth .field > span { font-size: 10px; letter-spacing: .12em; }
/* Der Zusatz in einem Feldnamen ist eine Nebenbemerkung, keine zweite Hälfte der
   Beschriftung — versalisiert liest sich „NEUES PASSWORT MINDESTENS 10 ZEICHEN" wie ein
   einziger Satzteil. */
.card.auth .field > span i {
  text-transform: none;
  letter-spacing: 0;
  font-size: 11px;
  color: var(--faint);
}
.card.auth .field > span i::before { content: "· "; }
.card.auth input {
  color: var(--ink);
  background: color-mix(in srgb, #000 34%, transparent);
  border: 1px solid color-mix(in srgb, #fff 11%, transparent);
  border-radius: 11px;
  padding: 12px 14px;
  font-size: 14px;
}
.card.auth input:-webkit-autofill,
.card.auth input:-webkit-autofill:hover,
.card.auth input:-webkit-autofill:focus { box-shadow: 0 0 0 1000px #0b0c10 inset; }
.card.auth input:focus {
  outline: none;
  border-color: color-mix(in srgb, var(--ember) 55%, transparent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ember) 16%, transparent);
}

/* Die Pille aus den Vorlagen: umrissen, nicht gefüllt. Gefüllt schreit, und auf einer
   Seite mit genau einer Handlung muss nichts schreien. */
.card.auth button[type=submit] {
  align-self: flex-start;
  margin-top: 6px;
  padding: 11px 26px;
  border-radius: 99px;
  background: none;
  color: var(--ink);
  border: 1px solid color-mix(in srgb, var(--ember) 62%, transparent);
  font-size: 13.5px;
  letter-spacing: .01em;
  transition: background .18s ease, border-color .18s ease;
}
.card.auth button[type=submit]:hover {
  filter: none;
  background: color-mix(in srgb, var(--ember) 14%, transparent);
  border-color: var(--ember);
}

/* ── Meldungen ─────────────────────────────────────────────────────────────── */

.alert {
  border: 1px solid color-mix(in srgb, #fff 8%, transparent);
  border-left: 2px solid var(--line);
  border-radius: 10px;
  padding: 11px 14px;
  font-size: 13px;
  line-height: 1.5;
  margin: 0 0 16px;
  background: color-mix(in srgb, #000 22%, transparent);
}
.alert.ok { border-left-color: var(--ok); }
.alert.bad { border-left-color: var(--bad); }
.alert.warn { border-left-color: var(--warn); }
/* Ein Passwort, das genau einmal zu sehen ist, muss sich in einem Zug markieren lassen. */
.sel { user-select: all; font-size: 15px; letter-spacing: .02em; }

.dim { color: var(--dim); }
.dim i, i.dim { font-style: normal; color: var(--faint); }
.small.dim, p.small { line-height: 1.55; }

.kv { display: grid; grid-template-columns: auto 1fr; gap: 8px 18px; margin: 0; font-size: 13.5px; }
.kv dt { color: var(--faint); font-size: 10px; text-transform: uppercase; letter-spacing: .14em; align-self: center; }
.kv dd { margin: 0; }

/* ── wer angemeldet ist ────────────────────────────────────────────────────── */

form.inline { display: inline; }
.whoami { display: flex; align-items: center; gap: 6px; }
.whoami a.ghost, .whoami button.ghost {
  text-decoration: none;
  border-radius: 99px;
  padding: 5px 13px;
  font-size: 11.5px;
  letter-spacing: .04em;
}
.whoami a.ghost:hover, .whoami button.ghost:hover { border-color: var(--ember); color: var(--ink); }

/* ── Verwaltung ────────────────────────────────────────────────────────────── */

/* Kein Leuchten hinter einer Tabelle: hier wird gelesen und entschieden, und Licht hinter
   Text ist genau da im Weg. Die Seite erbt nur die Form — Radien, Pillen, Abstände. */
.admin-head { margin: 30px 0 22px; }
.admin-head h1 { margin: 0 0 6px; font-size: clamp(24px, 4vw, 31px); font-weight: 640; letter-spacing: -.022em; }
.admin-head p { margin: 0; color: var(--dim); font-size: 13.5px; }

.card > h2 .badge.hot {
  color: var(--ember);
  border-color: color-mix(in srgb, var(--ember) 45%, transparent);
}

table.users { width: 100%; border-collapse: collapse; font-size: 13.5px; }
table.users th {
  text-align: left; font-size: 9.5px; text-transform: uppercase; letter-spacing: .16em;
  color: var(--faint); font-weight: 500; padding: 0 12px 10px 0;
}
table.users td { padding: 13px 12px 13px 0; border-top: 1px solid var(--line-soft); vertical-align: middle; }
table.users tbody tr:first-child td { border-top: none; }
table.users tr:hover td { background: color-mix(in srgb, #fff 2.5%, transparent); }
table.users td.who { width: 46%; }
table.users td.who b { font-weight: 550; letter-spacing: -.01em; }
table.users td.actions { text-align: right; white-space: nowrap; }
table.users td.actions form { margin-left: 6px; }
table.users td.actions button {
  border-radius: 99px; padding: 6px 14px; font-size: 12px;
}

/* Löschen steht in jeder Zeile. Ausgefüllt rot ist es damit das Lauteste auf einer Seite,
   auf der es das Seltenste sein sollte — also erst umrissen, gefüllt beim Zeigen. */
table.users td.actions button.danger {
  background: none;
  color: var(--bad);
  border: 1px solid color-mix(in srgb, var(--bad) 38%, transparent);
}
table.users td.actions button.danger:hover {
  filter: none;
  background: var(--bad);
  color: #180a09;
  border-color: var(--bad);
}

/* Der Zustand als Punkt plus Wort. Nur Farbe wäre für ein Achtel aller Männer keine
   Information; nur das Wort wäre in einer Liste von zwanzig Zeilen keins, das auffällt. */
.state { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }
.state::before {
  content: ""; width: 6px; height: 6px; border-radius: 99px;
  background: currentColor; box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 18%, transparent);
}
.state.st-active { color: var(--ok); }
.state.st-pending { color: var(--warn); }
.state.st-disabled, .state.st-rejected { color: var(--bad); }

.role { font-size: 12px; color: var(--dim); letter-spacing: .02em; }
.role.owner { color: var(--ember); }

table.users .badge {
  font-size: 9.5px; color: var(--faint); border: 1px solid var(--line);
  border-radius: 99px; padding: 2px 8px; margin-left: 6px; letter-spacing: .08em;
  text-transform: uppercase;
}

/* Nichts zu entscheiden ist ein Zustand, der es wert ist, gesagt zu werden — eine leere
   Tabelle sieht aus wie eine, die nicht geladen hat. */
.empty { color: var(--faint); font-size: 13px; padding: 6px 0 2px; }

/* ── klein ─────────────────────────────────────────────────────────────────── */

@media (max-width: 760px) {
  .card.auth { margin: 10px auto 30px; padding: 26px 22px 24px; border-radius: 18px; }
  .aurora::before { top: 40%; width: min(96vh, 128vw); }

  /* Vier Spalten nebeneinander sind auf dem Telefon vier unlesbare Spalten. Eine Zeile
     ist ein Mensch — also wird sie eine Karte. */
  table.users, table.users tbody, table.users tr, table.users td { display: block; width: 100%; }
  table.users thead { display: none; }
  table.users tr {
    border: 1px solid var(--line-soft); border-radius: 12px;
    padding: 12px 14px; margin-bottom: 10px;
  }
  table.users tr:hover td { background: none; }
  table.users td { border: none; padding: 3px 0; }
  table.users td.actions { text-align: left; white-space: normal; margin-top: 10px; }
  table.users td.actions form { margin: 0 6px 6px 0; display: inline-block; }
}
