:root {
  --bg: #f6f7f9;
  --panel: #ffffff;
  --ink: #1c2024;
  --muted: #6b7280;
  --line: #e3e6ea;
  --accent: #2f6feb;
  --ok: #128a4b;
  --warn: #b7791f;
  --bad: #c0392b;
}
* { box-sizing: border-box; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans SC", sans-serif;
}
.topbar {
  display: flex; align-items: center; gap: 20px;
  padding: 0 24px; height: 56px;
  background: var(--panel); border-bottom: 1px solid var(--line);
}
.brand {
  display: flex; align-items: center; gap: 10px;
  font-weight: 650; letter-spacing: .01em;
  color: var(--ink); text-decoration: none;
}
.brand:hover { color: var(--accent); }
/* The SVG has no width/height of its own, so the size lives here. */
.brand-logo { display: block; height: 28px; width: auto; }
.topbar nav { display: flex; gap: 16px; margin-left: auto; }
.topbar a { color: var(--ink); text-decoration: none; }
.topbar a:hover { color: var(--accent); }
main { max-width: 1080px; margin: 32px auto; padding: 0 24px; }
/* Aligned with main so the footer sits under the content rather than the
   viewport, and muted so it never competes with the page. */
.footer {
  max-width: 1080px; margin: 0 auto 40px; padding: 20px 24px 0;
  border-top: 1px solid var(--line);
  color: var(--muted); font-size: 13px;
  text-align: center;
}
.footer p { margin: 0 0 4px; }
.footer a { color: var(--muted); }
.footer a:hover { color: var(--accent); }
.card {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 10px; padding: 24px; margin-bottom: 24px;
}
.card.narrow { max-width: 560px; margin: 64px auto; }
h1 { font-size: 20px; margin: 0 0 16px; }
h2 { font-size: 16px; margin: 24px 0 12px; }
label { display: block; margin-bottom: 14px; font-size: 13px; color: var(--muted); }
input, select, textarea {
  display: block; width: 100%; margin-top: 5px; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 6px;
  font: inherit; color: var(--ink); background: #fff;
}
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); border-color: transparent; }
/* A checkbox is not a text field: the rule above would stretch it across the
   label and push its caption onto the next line. */
input[type="checkbox"] {
  display: inline-block; width: auto; margin: 0 6px 0 0; vertical-align: -1px;
}
label.check { color: var(--ink); font-size: 14px; }
button {
  padding: 8px 16px; border: 0; border-radius: 6px;
  background: var(--accent); color: #fff; font: inherit; cursor: pointer;
}
button:hover { filter: brightness(1.07); }
button.link { background: none; color: var(--muted); padding: 0; }
button.link:hover { color: var(--accent); filter: none; }
button.danger { background: var(--bad); }
form.inline { display: inline; }
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th, td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--line); }
th { color: var(--muted); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
tr:last-child td { border-bottom: 0; }
code, .mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px; background: #f1f3f5; padding: 2px 6px; border-radius: 4px;
}
.badge { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 12px; font-weight: 600; }
.badge.online { background: #e5f5ec; color: var(--ok); }
.badge.offline { background: #fdeceb; color: var(--bad); }
.badge.disabled { background: #f1f3f5; color: var(--muted); }
.badge.pending { background: #fdf6e3; color: var(--warn); }
.filters { display: flex; gap: 14px; font-size: 14px; }
.filters a { color: var(--muted); text-decoration: none; }
.filters a.active { color: var(--accent); font-weight: 600; }
.error { color: var(--bad); background: #fdeceb; padding: 10px 12px; border-radius: 6px; }
.notice { color: var(--warn); background: #fdf6e3; padding: 12px; border-radius: 6px; }
/* A value the user has to retype elsewhere: freely selectable text, with its own
   small button beside it, so dragging to select never fires a copy. */
.copy-row { display: flex; align-items: center; gap: 8px; margin: 0 0 16px; }
.copy-row code {
  flex: 1; min-width: 0; font-size: 15px; word-break: break-all;
  padding: 14px 16px; border-radius: 8px;
}
.copy-btn {
  flex: none; min-width: 78px; text-align: center;
  padding: 8px 10px; font-size: 13px;
  background: var(--panel); color: var(--muted);
  border: 1px solid var(--line); border-radius: 6px;
}
.copy-btn:hover { filter: none; border-color: var(--accent); color: var(--accent); }
.copy-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.copy-btn.copied { border-color: var(--ok); color: var(--ok); font-weight: 600; }
.copy-btn.failed { border-color: var(--bad); color: var(--bad); font-weight: 600; }
/* Dropdowns. The native <select> stays in the DOM as the value carrier and is
   hidden only once app.js has built the listbox that replaces it, so a browser
   that never runs the script still shows a working select. */
.select { position: relative; }
.select.ready > select { display: none; }
.select-trigger {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  width: 100%; text-align: left; cursor: pointer;
  padding: 8px 10px; font: inherit; color: var(--ink);
  background: #fff; border: 1px solid var(--line); border-radius: 6px;
}
.select-trigger:hover { border-color: var(--muted); }
.select-trigger[aria-expanded="true"] { border-color: var(--accent); }
.select-trigger:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.select-trigger:disabled { background: #f1f3f5; color: var(--muted); cursor: default; }
.select-value { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.select-value.placeholder { color: var(--muted); }
.select-arrow { flex: none; color: var(--muted); transition: transform .12s ease; }
.select-trigger[aria-expanded="true"] .select-arrow { transform: rotate(180deg); }
.select-menu {
  position: absolute; z-index: 20; left: 0; right: 0; top: calc(100% + 4px);
  margin: 0; padding: 4px; list-style: none;
  max-height: 260px; overflow-y: auto;
  background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 10px 24px rgba(28, 32, 36, .12);
}
.select-menu[hidden] { display: none; }
.select.drop-up .select-menu { top: auto; bottom: calc(100% + 4px); }
.select-option { padding: 8px 10px; border-radius: 6px; cursor: pointer; }
.select-option.active { background: #eef2fb; }
.select-option[aria-selected="true"] { color: var(--accent); font-weight: 600; }
.select-option[aria-selected="true"]::after { content: "✓"; float: right; }
.select-option.disabled { color: var(--muted); cursor: default; }
.select.invalid .select-trigger { border-color: var(--bad); }
a.btn, .btn {
  display: inline-block; padding: 8px 16px; border-radius: 6px;
  background: var(--accent); color: #fff; text-decoration: none;
}
a.btn.secondary, .btn.secondary {
  background: var(--panel); color: var(--ink); border: 1px solid var(--line);
}
a.btn.secondary:hover, .btn.secondary:hover {
  border-color: var(--accent); color: var(--accent); filter: none;
}
/* Confirmation dialog. The behaviour is the platform's — modal focus handling,
   Esc to dismiss, an inert page behind — and every pixel of it is ours, which
   is the whole reason it is a <dialog> and not window.confirm(). */
.modal {
  width: min(440px, calc(100vw - 32px));
  padding: 24px; border: 0; border-radius: 12px;
  background: var(--panel); color: var(--ink);
  box-shadow: 0 24px 60px rgba(28, 32, 36, .24);
}
.modal::backdrop { background: rgba(28, 32, 36, .42); }
.modal h2 { margin: 0 0 8px; font-size: 16px; }
.modal-message { margin: 0 0 20px; color: var(--muted); }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; }
td.actions { white-space: nowrap; }
td.actions form { display: inline; }
td.actions button { padding: 4px 10px; font-size: 13px; margin-right: 4px; }
.muted { color: var(--muted); }
