/* Stack portal: the "dark console" style agreed in brainstorming, with a light
   variant that follows the OS setting. Every colour is a token on :root, so the
   light variant only swaps tokens. The CSP has no 'unsafe-inline': all looks live
   here, as classes; app.js never sets a style. */

:root {
  color-scheme: dark;
  --bg: #0e1116;
  --bg-deep: #0b0d11;
  --panel: #11151b;
  --sel: #161b22;
  --line: #262c36;
  --line-soft: #1f2630;
  --line-input: #30363d;
  --text: #e6edf3;
  --text-soft: #c9d1d9;
  --dim: #8b949e;
  --faint: #848d97;
  --go: #22c55e;
  --go-ink: #06270f;
  --go-hover: #16a34a;
  --ok: #4ade80;
  --ok-bg: #16361f;
  --run: #3b82f6;
  --run-ink: #93c5fd;
  --run-bg: #13294a;
  --err: #fda4af;
  --err-bg: #3b1219;
  --err-line: #5c2430;
  --err-box: #1f0d12;
  --danger: #dc2626;
  --danger-ink: #ffffff;
  --danger-off: #7f4b53;
  --warn: #fcd34d;
  --warn-bg: #2a2110;
  --warn-line: #5c4715;
  --wait-bg: #1c222b;
  --focus: #60a5fa;
  --avatar: #3b82f6;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  /* Installed faces only: the CSP loads no font from anywhere. Avenir Next on macOS, Segoe UI on Windows,
     URW Gothic on Linux, then whatever the system sets. */
  --sans: "Avenir Next", Avenir, "Segoe UI Variable Text", "Segoe UI", "URW Gothic", system-ui, sans-serif;
}

@media (prefers-color-scheme: light) {
  :root {
    color-scheme: light;
    --bg: #ffffff;
    --bg-deep: #f6f8fa;
    --panel: #f6f8fa;
    --sel: #eaeef2;
    --line: #d0d7de;
    --line-soft: #e1e4e8;
    --line-input: #d0d7de;
    --text: #1f2328;
    --text-soft: #32383f;
    --dim: #59636e;
    --faint: #626a73;
    --go: #1a7f37;
    --go-ink: #ffffff;
    --go-hover: #116329;
    --ok: #1a7f37;
    --ok-bg: #dafbe1;
    --run: #0969da;
    --run-ink: #0550ae;
    --run-bg: #ddf4ff;
    --err: #cf222e;
    --err-bg: #ffebe9;
    --err-line: #ffcecb;
    --err-box: #fff5f5;
    --danger: #cf222e;
    --danger-ink: #ffffff;
    --danger-off: #d4868b;
    --warn: #7d4e00;
    --warn-bg: #fff8c5;
    --warn-line: #eac54f;
    --wait-bg: #eaeef2;
    --focus: #0969da;
    --avatar: #0969da;
  }
}

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

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; }
body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--text);
  font: 14px/1.5 var(--sans);
}
a { color: var(--run-ink); }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.mono { font-family: var(--mono); font-size: 12.5px; }
.dim { color: var(--dim); }
.hint { margin: 4px 0 0; color: var(--dim); font-size: 12px; }
.loading, .empty { margin: 0; color: var(--dim); font-size: 13px; }
.loading { padding: 24px 16px; }
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ------------------------------------------------------------------ top bar and banners */

.top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 16px;
  background: var(--bg-deep);
  border-bottom: 1px solid var(--line);
}
.brand { align-self: stretch; display: inline-flex; align-items: center; gap: 10px; font-family: var(--mono); font-weight: 600; letter-spacing: .3px; }
/* The mark: blocks hanging from one edge like a pipeline's steps (done, running, destroy, waiting), with the
   step dots cut out of them. The cut is the colour of the ground the mark sits on. In the top bar the edge
   is the window's: the brand is as tall as the bar, and the negative margin is the bar's own top padding. */
.logo { flex: none; align-self: flex-start; width: 72px; height: 30px; margin-top: -10px; }
.logo .l-go { fill: var(--go); }
.logo .l-run { fill: var(--run); }
.logo .l-danger { fill: var(--danger); }
.logo .l-wait { fill: var(--line-input); }
.logo .l-cut { fill: var(--bg-deep); }
.logo .l-tint { fill: var(--run-bg); }
.who { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px; font-size: 13px; }
.who-error { color: var(--err); font-size: 12px; }
.av {
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--avatar);
  color: #ffffff;
  font-size: 11px;
  font-weight: 600;
  object-fit: cover;
}

.banners:empty { display: none; }
.banner { padding: 8px 16px; font-size: 13px; border-bottom: 1px solid; }
.banner.warn { background: var(--warn-bg); color: var(--warn); border-color: var(--warn-line); }
.banner.error { background: var(--err-box); color: var(--err); border-color: var(--err-line); }

/* ------------------------------------------------------------------ layout: list left, detail right */

.app {
  flex: 1;
  display: grid;
  grid-template-columns: minmax(230px, 320px) minmax(0, 1fr);
}
.app.solo { display: block; padding: 0 16px; }

.side { padding: 12px 0; background: var(--bg-deep); border-right: 1px solid var(--line); }
.side > .btn { margin: 0 14px 6px; width: calc(100% - 28px); }
.grp-title {
  margin: 14px 14px 4px;
  color: var(--dim);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .6px;
  text-transform: uppercase;
}
.grp-title .count { color: var(--faint); }
.grp ul { list-style: none; margin: 0; padding: 0; }
.grp .empty { padding: 4px 14px; }
.item {
  display: block;
  width: 100%;
  padding: 8px 14px 8px 11px;
  text-align: left;
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  border-left: 3px solid transparent;
  cursor: pointer;
}
.item:hover { background: var(--panel); }
.item[aria-current="true"] { background: var(--sel); border-left-color: var(--go); }
.item:focus-visible { outline-offset: -2px; }
.item-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.item b { font-weight: 600; overflow-wrap: anywhere; }
.item small { display: block; color: var(--dim); font-size: 12px; }

.detail { min-width: 0; padding: 18px 22px 40px; }
.ttl { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.ttl h2 { margin: 0; font-size: 18px; font-weight: 650; overflow-wrap: anywhere; }
.ttl h2:focus { outline: none; }
.detail h3 {
  margin: 24px 0 8px;
  color: var(--dim);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .6px;
  text-transform: uppercase;
}
.owner { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 8px 0 0; }

.facts { display: flex; flex-wrap: wrap; gap: 6px 24px; margin: 12px 0 0; }
.facts dt { color: var(--dim); font-size: 11px; letter-spacing: .5px; text-transform: uppercase; }
.facts dd { margin: 0; font-family: var(--mono); font-size: 12.5px; }
.flags { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; margin: 12px 0 0; padding: 0; }
.flags li {
  padding: 2px 8px;
  border-radius: 6px;
  font: 11px/1.6 var(--mono);
  background: var(--warn-bg);
  color: var(--warn);
  border: 1px solid var(--warn-line);
}
.notice {
  margin: 0 0 14px;
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 13px;
  background: var(--run-bg);
  color: var(--run-ink);
}

/* ------------------------------------------------------------------ badges */

.badge {
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
  background: var(--wait-bg);
  color: var(--dim);
}
.badge-creating, .badge-extending, .badge-destroying { background: var(--run-bg); color: var(--run-ink); }
.badge-k3s_ready { background: var(--ok-bg); color: var(--ok); }
.badge-expiring_soon { background: var(--warn-bg); color: var(--warn); }
.badge-failed, .badge-expired { background: var(--err-bg); color: var(--err); }

/* ------------------------------------------------------------------ progress */

.steps { display: flex; flex-direction: column; gap: 8px; list-style: none; margin: 0; padding: 0; }
.step {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 8px;
  font: 12.5px/1.4 var(--mono);
  background: var(--panel);
  border: 1px solid var(--line-soft);
}
.step .name { flex: 1; }
.step .t { color: var(--dim); font-variant-numeric: tabular-nums; }
.dot {
  flex: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  background: var(--wait-bg);
  color: var(--faint);
}
.step.ok .dot { background: var(--ok-bg); color: var(--ok); }
.step.run .dot { background: var(--run-bg); color: var(--run-ink); animation: pulse 1.6s ease-in-out infinite; }
.step.fail { color: var(--err); border-color: var(--err-line); }
.step.fail .dot { background: var(--err-bg); color: var(--err); }
.step.skip, .step.wait .name { color: var(--faint); }
@keyframes pulse { 50% { opacity: .45; } }

progress {
  display: block;
  width: 100%;
  height: 6px;
  margin: 14px 0 6px;
  border: 0;
  border-radius: 3px;
  overflow: hidden;
  appearance: none;
  background: var(--wait-bg);
}
progress::-webkit-progress-bar { background: var(--wait-bg); }
progress::-webkit-progress-value { background: linear-gradient(90deg, var(--go), var(--run)); }
progress::-moz-progress-bar { background: linear-gradient(90deg, var(--go), var(--run)); }

/* ------------------------------------------------------------------ nodes, commands, log */

.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th {
  padding: 6px 12px 6px 0;
  text-align: left;
  color: var(--dim);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .5px;
  text-transform: uppercase;
  border-bottom: 1px solid var(--line);
}
td { padding: 7px 12px 7px 0; white-space: nowrap; border-bottom: 1px solid var(--line-soft); }
.state.running { color: var(--ok); }
.state.pending, .state.stopping { color: var(--run-ink); }
.state.stopped { color: var(--warn); }

pre {
  margin: 0;
  padding: 8px 12px;
  overflow-x: auto;
  font: 12px/1.5 var(--mono);
  color: var(--text-soft);
  background: var(--bg-deep);
  border: 1px solid var(--line);
  border-radius: 8px;
}
.cmd { margin: 0 0 10px; }
.cmd-label { margin-bottom: 4px; color: var(--dim); font-size: 12px; }
.cmd-line { display: flex; align-items: flex-start; gap: 8px; }
/* Wrapped, so the whole command is visible before it is copied. */
.cmd-line pre { flex: 1; min-width: 0; white-space: pre-wrap; word-break: break-all; }
.log { max-height: 360px; margin: 10px 0; overflow: auto; white-space: pre; }
.log .e { color: var(--err); }

/* ------------------------------------------------------------------ forms and buttons */

label {
  display: block;
  margin-bottom: 4px;
  color: var(--dim);
  font-size: 11px;
  letter-spacing: .5px;
  text-transform: uppercase;
}
input, select {
  width: 100%;
  min-height: 34px;
  padding: 6px 10px;
  font: 12.5px var(--mono);
  color: var(--text);
  background: var(--bg-deep);
  border: 1px solid var(--line-input);
  border-radius: 7px;
}
input:focus-visible, select:focus-visible { outline: 2px solid var(--focus); outline-offset: 0; border-color: var(--run); }
input:user-invalid { border-color: var(--err); }
.grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 16px; margin: 16px 0; }
.est {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 28px;
  margin: 0;
  padding: 10px 14px;
  background: var(--panel);
  border: 1px solid var(--line-soft);
  border-radius: 8px;
}
.est b { display: block; font: 600 15px var(--mono); }
.est span { color: var(--dim); font-size: 12px; }
.row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 12px; }
.action { margin: 0 0 16px; }
.extend .row, .add-nodes .row { margin-top: 0; }
.extend select, .add-nodes select { width: auto; min-width: 190px; }
.destroy input { max-width: 280px; }
.warnbox {
  margin: 10px 0 14px;
  padding: 10px 12px;
  font-size: 13px;
  background: var(--err-box);
  border: 1px solid var(--err-line);
  border-radius: 8px;
}
.form-error {
  margin: 12px 0 0;
  padding: 8px 12px;
  font-size: 13px;
  color: var(--err);
  background: var(--err-box);
  border: 1px solid var(--err-line);
  border-radius: 8px;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 34px;
  padding: 6px 14px;
  font: 600 13px var(--sans);
  text-decoration: none;
  color: var(--text-soft);
  background: var(--panel);
  border: 1px solid transparent;
  border-radius: 7px;
  cursor: pointer;
}
.btn.go { background: var(--go); color: var(--go-ink); }
.btn.go:hover:enabled, a.btn.go:hover { background: var(--go-hover); }
.btn.ghost { background: transparent; color: var(--text-soft); border-color: var(--line-input); }
.btn.ghost:hover:enabled { background: var(--panel); }
.btn.danger { background: var(--danger); color: var(--danger-ink); }
.btn.danger-ghost { background: transparent; color: var(--err); border-color: var(--err-line); }
.btn.small { min-height: 28px; padding: 3px 10px; font-size: 12px; }
.btn:disabled { cursor: not-allowed; opacity: .55; }
.btn.danger:disabled { opacity: 1; background: var(--err-bg); color: var(--danger-off); }
.btn[aria-current="true"] { box-shadow: inset 0 0 0 2px var(--go-ink); }

/* ------------------------------------------------------------------ signed out */

.signin {
  max-width: 420px;
  margin: 12vh auto 0;
  padding: 28px;
  text-align: center;
  background: var(--bg-deep);
  border: 1px solid var(--line);
  border-radius: 12px;
}
.signin h1 { margin: 0 0 8px; font: 600 18px var(--mono); }
.signin p { margin: 0 0 18px; color: var(--text-soft); }
.signin .hint { margin: 14px 0 0; color: var(--dim); }

/* ------------------------------------------------------------------ narrow screens and motion */

@media (max-width: 760px) {
  .app { grid-template-columns: minmax(0, 1fr); }
  .side { border-right: 0; border-bottom: 1px solid var(--line); }
  .brand { align-items: flex-start; }   /* the bar wraps to two rows here: the name stays on the mark's */
  .detail { padding: 16px; }
  .grid { grid-template-columns: minmax(0, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
  .step.run .dot { animation: none; }
}
