/* Light is the base. Dark applies when the OS asks for it, unless the operator
   picked light; an explicit choice wins over the OS either way. */
:root {
  color-scheme: light;
  --bg: #fbfaf8; --fg: #1e1c1a; --muted: #6b6560; --line: #e2ddd6;
  --card: #ffffff; --accent: #8a4b2a; --ok: #2e6b45; --warn: #8a6a1f; --err: #9b2c2c;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg:#17161a; --fg:#eceaf0; --muted:#9b95a3; --line:#33303a;
    --card:#1f1e24; --accent:#d69a6a; --ok:#6ec48f; --warn:#d9b45b; --err:#e08a8a; }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg:#17161a; --fg:#eceaf0; --muted:#9b95a3; --line:#33303a;
  --card:#1f1e24; --accent:#d69a6a; --ok:#6ec48f; --warn:#d9b45b; --err:#e08a8a; }
* { box-sizing: border-box; }
body { margin:0; background:var(--bg); color:var(--fg);
  font:15px/1.55 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; }
main { max-width: 1040px; margin: 0 auto; padding: 1.5rem 1.25rem 4rem; }
a { color: var(--accent); }
code { font: 13px/1.4 ui-monospace, "SF Mono", Menlo, monospace;
  background: color-mix(in srgb, var(--fg) 7%, transparent);
  padding: .1em .35em; border-radius: 4px; }
h1 { font-size: 1.6rem; margin: .2rem 0 .4rem; }
h2 { font-size: 1.05rem; margin: 0 0 .6rem; letter-spacing: .01em; }
.muted { color: var(--muted); font-size: .875rem; }

.topbar { display:flex; justify-content:space-between; align-items:center; gap:1rem;
  padding:.7rem 1.25rem; border-bottom:1px solid var(--line); background:var(--card); }
.topbar .brand { font-weight:650; text-decoration:none; color:var(--fg); }
.topbar nav { display:flex; align-items:center; gap:.75rem; }
.who { font-size:.85rem; color:var(--muted); }
.role { border:1px solid var(--line); border-radius:99px; padding:0 .45em; margin-left:.25em; }

.flash { padding:.6rem .8rem; border-radius:8px; margin-bottom:1rem; font-size:.9rem; }
.flash.notice { background:color-mix(in srgb,var(--ok) 15%,transparent); color:var(--ok); }
.flash.alert  { background:color-mix(in srgb,var(--err) 15%,transparent); color:var(--err); }

.page-head { display:flex; justify-content:space-between; align-items:flex-start;
  gap:1rem; flex-wrap:wrap; margin-bottom:1rem; }
.page-head .actions { display:flex; gap:.5rem; flex:0 0 auto; padding-top:1.2rem; }
.page-head p { margin:.2rem 0; }

.card { background:var(--card); border:1px solid var(--line); border-radius:10px;
  padding:1rem; margin:0 0 1rem; }
.card.warn { border-color:color-mix(in srgb,var(--warn) 45%,var(--line)); }
.grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(300px,1fr)); gap:1rem; }
.tasks { font-size:.85rem; line-height:2; }

.badge { display:inline-block; font-size:.7rem; text-transform:uppercase; letter-spacing:.04em;
  border:1px solid var(--line); border-radius:99px; padding:.05em .5em; margin-left:.3em;
  color:var(--muted); vertical-align:middle; }
.badge.gate { border-color:var(--warn); color:var(--warn); }
.badge.paused { border-color:var(--err); color:var(--err); }

.status { font-size:.78rem; font-weight:600; text-transform:uppercase; letter-spacing:.04em; }
.status.success, .status.active { color:var(--ok); }
.status.failed, .status.cancelled { color:var(--err); }
.status.awaiting_approval, .status.paused, .status.waiting { color:var(--warn); }
.status.running, .status.queued, .status.pending, .status.draft { color:var(--muted); }
.status.skipped { color:var(--muted); }

/* One card per task. The left edge carries the status, so a run's state is
   readable down the margin without reading a word. */
.task { border:1px solid var(--line); border-left-width:3px; border-radius:8px;
  padding:.55rem .75rem; margin-bottom:.5rem; }
.task.success { border-left-color:var(--ok); }
.task.failed  { border-color:color-mix(in srgb,var(--err) 35%,var(--line));
  border-left-color:var(--err); }
.task.running { border-left-color:var(--accent); }
.task-head { display:flex; align-items:center; gap:.55rem; flex-wrap:wrap; }
.task-head .facts { margin-left:auto; display:flex; gap:.75rem; flex-wrap:wrap;
  color:var(--muted); font-size:.8rem; }
.task-head .btn { font-size:.8rem; padding:.25rem .8rem; }
.task .err, .task .muted { margin:.35rem 0 0; }

table.runs { width:100%; border-collapse:collapse; font-size:.9rem; margin-bottom:1rem; }
table.runs th { text-align:left; font-size:.72rem; text-transform:uppercase;
  letter-spacing:.05em; color:var(--muted); border-bottom:1px solid var(--line);
  padding:.4rem .5rem; font-weight:600; }
table.runs td { padding:.45rem .5rem; border-bottom:1px solid var(--line); vertical-align:top; }
.err { color:var(--err); font-size:.85rem; }

/* Configuration grid: many columns, so the setting name stays put while the
   clients scroll under it. */
.matrix-scroll { overflow-x:auto; }
table.matrix th { text-align:center; }
table.matrix th.rowhead { text-align:left; }
table.matrix td.cell { text-align:center; vertical-align:middle; white-space:nowrap; }
table.matrix td.cell input[type=text], table.matrix td.cell input[type=number] {
  width:7rem; text-align:center; }
table.matrix input[type=checkbox] { accent-color:var(--accent); width:1.05rem; height:1.05rem; }
table.matrix td.cell input:disabled { opacity:.4; cursor:not-allowed; }

/* A classification spanning its rows. Static, and it turns off the sticky name
   column: two sticky cells at left:0 would sit on top of each other. */
table.matrix td.classcol, table.matrix th.classcol { font-size:.72rem; font-weight:600;
  text-transform:uppercase; letter-spacing:.05em; color:var(--muted);
  vertical-align:middle; border-right:1px solid var(--line); white-space:nowrap;
  padding:.45rem .7rem; }
table.matrix.has-classcol .rowhead { position:static; }

/* Addresses sit with the message they are for, one line per client, so each field
   has the width an address needs. */
table.addresses { table-layout:fixed; }
table.addresses th:first-child, table.addresses td:first-child { width:9rem; }
table.addresses .rowhead { position:static; font-size:.9rem; }
table.addresses input { width:100%; text-align:left; }

/* What a message will say, read-only: label above value, not a form. */
dl.wording { display:grid; grid-template-columns:max-content 1fr; gap:.35rem 1rem;
  align-items:baseline; margin:0 0 1rem; font-size:.9rem; }
dl.wording dt { color:var(--muted); font-size:.78rem; text-transform:uppercase;
  letter-spacing:.05em; }
dl.wording dd { margin:0; min-width:0; }

/* Wording a client reads. Monospace because placeholders are literal. Only the
   textarea gets a box — a bordered block reads as a field you can type in. */
textarea.template-body { width:100%; font:inherit;
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:.85rem;
  line-height:1.5; padding:.6rem .7rem; border:1px solid var(--line);
  border-radius:6px; background:var(--bg); color:var(--fg); }

/* Text you are shown, not text you fill in. */
pre.quoted, blockquote.quoted { margin:.1rem 0 .4rem; padding:.1rem 0 .1rem .9rem;
  border-left:2px solid var(--line); color:var(--muted); font-size:.85rem;
  line-height:1.5; background:none; }
pre.quoted { white-space:pre-wrap;
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace; }

/* A disclosure styled as a button, so editing is deliberate and needs no JS. */
details.reveal { margin:.2rem 0 .6rem; }
details.reveal > summary { display:inline-block; cursor:pointer; font-size:.8rem;
  padding:.25rem .7rem; border:1px solid var(--line); border-radius:6px;
  color:var(--fg); list-style:none; }
details.reveal > summary::-webkit-details-marker { display:none; }
details.reveal > summary:hover { border-color:var(--accent); color:var(--accent); }
/* Save sits beside Modify while open, and the field starts on its own line. */
details.reveal > input[type=submit] { margin-left:.4rem; font-size:.8rem;
  padding:.25rem .8rem; }
details.reveal > textarea { display:block; margin-top:.5rem; }

/* Groups within one block — params from deliverables from checks. A ruled caption
   rather than a badge: it separates without competing with the row labels. */
table.matrix tr.group td { border-bottom:none; padding:1rem .5rem .2rem; }
table.matrix tr.group .rowhead { position:static; font-size:.7rem; font-weight:600;
  text-transform:uppercase; letter-spacing:.08em; color:var(--muted);
  border-top:1px solid var(--line); }
table.matrix tr.group:first-child .rowhead { border-top:none; padding-top:.2rem; }

/* Produce and send read as one control per client, so they sit together. */
.pair { display:inline-flex; align-items:center; gap:.4rem; }
.pipe { color:var(--line); }
.badge.on { border-color:var(--ok); color:var(--ok); }
table.matrix .rowhead { position:sticky; left:0; background:var(--card);
  min-width:16rem; white-space:nowrap; }
table.matrix th:first-child { z-index:1; }
table.matrix .na { font-size:.8rem; }

ul.list, ol.list { margin:0; padding-left:1.1rem; }
ul.list li, ol.list li { margin:.25rem 0; }

.row { display:flex; flex-wrap:wrap; gap:.75rem; align-items:flex-end; }
.row label { display:flex; flex-direction:column; gap:.2rem; font-size:.8rem; color:var(--muted); }
.row label.check { flex-direction:row; align-items:center; gap:.35rem; }
input, select { font:inherit; padding:.35rem .5rem; border:1px solid var(--line);
  border-radius:6px; background:var(--bg); color:var(--fg); }
.btn, input[type=submit] { font:inherit; font-size:.9rem; padding:.4rem .9rem; border-radius:6px;
  border:1px solid var(--accent); background:var(--accent); color:#fff; cursor:pointer; }
.btn.danger { background:transparent; color:var(--err); border-color:var(--err); }
.btn.ghost { background:transparent; color:var(--accent); }
a.btn { text-decoration:none; display:inline-block; }
.linkish { background:none; border:none; color:var(--accent); cursor:pointer;
  font:inherit; font-size:.85rem; padding:0; text-decoration:underline; }
form { display:inline; }

.logs { font:12.5px/1.6 ui-monospace, "SF Mono", Menlo, monospace;
  max-height:22rem; overflow-y:auto; background:var(--bg);
  border:1px solid var(--line); border-radius:8px; padding:.6rem; }
.logline { display:flex; gap:.6rem; }
.logline .ts { color:var(--muted); flex:0 0 auto; }
.logline.error .msg { color:var(--err); }
.logline.warning .msg { color:var(--warn); }
.runhead { display:flex; align-items:center; gap:.75rem; margin:.5rem 0 1rem; }
.badge.error { border-color:var(--err); color:var(--err); }
.badge.warning { border-color:var(--warn); color:var(--warn); }

.crumbs { display:flex; flex-wrap:wrap; align-items:center; gap:.4rem;
  font-size:.85rem; color:var(--muted); margin:0 0 .75rem; }
.crumbs .sep { color:var(--line); }
.crumbs [aria-current] { color:var(--fg); font-weight:550; }

.year { margin-bottom:1.25rem; }
.year h3 { margin:.25rem 0 .5rem; font-size:.9rem; color:var(--muted);
  letter-spacing:.06em; }
.period-grid { display:grid; grid-template-columns:repeat(var(--cols),1fr); gap:.5rem; }
.period { display:flex; flex-direction:column; gap:.15rem; padding:.5rem .6rem;
  border:1px solid var(--line); border-left-width:3px; border-radius:8px;
  text-decoration:none; color:var(--fg); }
.period:hover { border-color:var(--accent); }
.period .label { font-weight:600; font-size:.85rem; }
.period.success { border-left-color:var(--ok); }
.period.failed, .period.missing { border-left-color:var(--err); }
.period.running, .period.queued, .period.waiting { border-left-color:var(--accent); }
.period.future { opacity:.4; }
.badge.warn { border-color:var(--warn); color:var(--warn); }
