/* console/assets/console.css - The one stylesheet.
 *
 * The palette came from the dashboard this replaced (#667eea → #764ba2, the alert
 * greens/ambers/reds, the #1e1e1e log), so the tool still looks like itself. Layout:
 * fixed sidebar, top bar, one content column, a result drawer that sticks to the
 * bottom. */

:root {
    --c-primary: #667eea;
    --c-primary-2: #764ba2;
    --c-bg: #f5f7fa;
    --c-surface: #fff;
    --c-line: #e8eaf0;
    --c-text: #24292f;
    --c-muted: #6b7280;
    --c-ok-bg: #d4edda;   --c-ok: #155724;   --c-ok-line: #28a745;
    --c-warn-bg: #fff3cd; --c-warn: #856404; --c-warn-line: #ffc107;
    --c-bad-bg: #f8d7da;  --c-bad: #721c24;  --c-bad-line: #dc3545;
    --c-info-bg: #d1ecf1; --c-info: #0c5460; --c-info-line: #17a2b8;
    --c-log: #1e1e1e; --c-log-text: #f8f8f2;
    --radius: 8px;
    --shadow: 0 2px 8px rgba(0,0,0,.08);
    --sidebar: 240px;
    --grad: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    --grad-go: linear-gradient(135deg, #28a745 0%, #20c997 100%);
    --grad-bad: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
    --mono: ui-monospace, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }
html { font-size: 15px; }
body {
    margin: 0; background: var(--c-bg); color: var(--c-text);
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    line-height: 1.45;
}
a { color: var(--c-primary); }
code { background: #f0f2f5; padding: .12rem .4rem; border-radius: 4px; font-family: var(--mono); font-size: .88em; }
code.sha { letter-spacing: .02em; }
.muted { color: var(--c-muted); }
.small { font-size: .88em; }
.skip { position: absolute; left: -999px; top: 0; }
.skip:focus { left: .5rem; top: .5rem; background: #fff; padding: .5rem; z-index: 50; }

/* ── Sidebar ─────────────────────────────────────────────────────────── */
.sidebar {
    position: fixed; inset: 0 auto 0 0; width: var(--sidebar);
    background: #fff; border-right: 1px solid var(--c-line);
    display: flex; flex-direction: column; z-index: 20;
}
.brand { display: flex; align-items: center; justify-content: space-between; padding: 1rem 1rem .75rem; }
.brand a { display: flex; align-items: center; gap: .5rem; text-decoration: none; color: var(--c-text); font-weight: 700; font-size: .9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.brand img { display: block; height: 24px; flex: none; }
.sidebar nav { flex: 1; overflow-y: auto; padding: .25rem 0 1rem; }
.nav-group { padding: 1rem 1rem .3rem; font-size: .72rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--c-muted); }
.sidebar nav a {
    display: flex; align-items: center; gap: .6rem; padding: .5rem 1rem; margin: 0 .5rem; border-radius: 6px;
    text-decoration: none; color: #374151; font-weight: 500;
}
.sidebar nav a:hover { background: #f3f4f8; color: var(--c-primary); }
.sidebar nav a.active { background: var(--grad); color: #fff; }
.sidebar nav a .ico { width: 1.4rem; text-align: center; }
.sidebar nav a .ext { margin-left: auto; color: var(--c-muted); font-size: .8em; }
.sidebar nav a.active .ext { color: #fff; }
/* Project shortcuts under a page that works on more than one. Indented under the item
   they belong to, lighter than it, and never wider than the sidebar: project names carry
   a leading emoji and can be long, so they ellipsis and keep the full name on hover. */
.sidebar nav a.nav-sub {
    padding: .3rem 1rem .3rem 2.6rem; margin: 0 .5rem; font-size: .84rem; font-weight: 400;
    color: var(--c-muted); display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sidebar nav a.nav-sub:hover { background: #f3f4f8; color: var(--c-primary); }
.sidebar nav a.nav-sub.active { background: #eef0fb; color: var(--c-primary); font-weight: 600; }
.sidebar-foot { display: flex; align-items: center; gap: .75rem; padding: .9rem 1rem; border-top: 1px solid var(--c-line); font-size: .9rem; }
.sidebar-foot .who a { text-decoration: none; color: var(--c-text); }
.sidebar-foot .logout { margin-left: .5rem; color: var(--c-bad-line); font-weight: 600; font-size: .85em; }
.avatar {
    width: 38px; height: 38px; border-radius: 50%; background: var(--grad); color: #fff;
    display: flex; align-items: center; justify-content: center; font-weight: 700; flex: none;
}
.nav-toggle, .nav-open, .nav-close, .nav-scrim { display: none; }

/* ── Page column ─────────────────────────────────────────────────────── */
.page { margin-left: var(--sidebar); min-height: 100vh; display: flex; flex-direction: column; }
.topbar {
    position: sticky; top: 0; z-index: 10; display: flex; align-items: center; gap: 1rem;
    padding: .6rem 1.5rem; background: rgba(255,255,255,.92); backdrop-filter: blur(6px);
    border-bottom: 1px solid var(--c-line); min-height: 3.2rem;
}
.topbar-right { margin-left: auto; }
.pills { display: flex; gap: .4rem; flex-wrap: wrap; }
.pill {
    padding: .35rem .8rem; border: 2px solid var(--c-line); border-radius: 999px; background: #fff;
    text-decoration: none; color: #555; font-weight: 600; font-size: .88rem;
}
.pill:hover { border-color: var(--c-primary); color: var(--c-primary); }
.pill.active { background: var(--grad); border-color: var(--c-primary); color: #fff; }
.ip-display { font-size: .8rem; color: var(--c-muted); }

/* No cap: what these pages hold is tables and workspace grids — the history log, the
   status check, the audit trail, the workspace tick-boxes — and every one of them is
   easier to read with the width than without it. A line of prose is not, so the two
   places that are prose carry their own measure: .blurb below and .prose further down. */
main { flex: 1; width: 100%; padding: 1.25rem 1.5rem 2rem; }
.crumbs { font-size: .8rem; color: var(--c-muted); margin-bottom: .2rem; }
main h1 { margin: 0 0 .25rem; font-size: 1.55rem; }
.blurb { margin: 0 0 1.25rem; color: var(--c-muted); max-width: 80ch; }
.frozen { background: var(--c-bad-bg); color: var(--c-bad); padding: 1rem; border-radius: var(--radius); font-weight: 600; margin-bottom: 1.25rem; border-left: 4px solid var(--c-bad-line); }

/* ── Cards & notes ───────────────────────────────────────────────────── */
.card { background: var(--c-surface); border-radius: 10px; padding: 1.25rem 1.5rem; margin-bottom: 1.25rem; box-shadow: var(--shadow); }
.card h2 { margin: 0 0 .75rem; font-size: 1.15rem; color: #333; }
.card h3 { margin: 1rem 0 .5rem; font-size: 1rem; color: #444; }
.card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.card-head h2 { margin-bottom: .25rem; }
.cards-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 1.25rem; margin-bottom: 1.25rem; }
.cards-2 .card { margin-bottom: 0; }
/* Sentences keep a measure even though their card does not: a table wants the width, an
   explanation of what a button will do wants to be read. Tables, grids and forms are
   unaffected — only the paragraphs a card holds directly. */
.card > p, .card > ol, .card > ul, .note { max-width: 100ch; }
.note { padding: .75rem 1rem; border-radius: 6px; margin: .5rem 0 1rem; font-size: .92rem; }
.note-info { background: #e3f2fd; color: #1976d2; }
.note-info code { background: #bbdefb; }
.note-warn { background: var(--c-warn-bg); color: var(--c-warn); }
.note-prod { background: var(--c-info-bg); color: var(--c-info); }
.note-bad { background: var(--c-bad-bg); color: var(--c-bad); }
.alert { padding: .75rem; border-radius: 6px; margin: 1rem 0; }
.alert-error { background: #fee; color: #c00; border-left: 4px solid #c00; }
.empty { color: var(--c-muted); font-style: italic; }

/* ── Tables ──────────────────────────────────────────────────────────── */
.table-wrap { overflow-x: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: .92rem; }
table.data th, table.data td { padding: .55rem .6rem; text-align: left; border-bottom: 1px solid #eee; vertical-align: top; }
table.data th { background: #f8f9fa; font-weight: 600; color: #444; white-space: nowrap; }
table.data tr.row-bad { background: var(--c-bad-bg); }
table.data tr.row-bad td { color: var(--c-bad); }
table.data td.num { white-space: nowrap; }
.ok { color: var(--c-ok); font-weight: 600; }
.warn { color: var(--c-bad); font-weight: 600; }

/* ── Badges ──────────────────────────────────────────────────────────── */
.badge { display: inline-block; padding: .18rem .6rem; border-radius: 20px; font-size: .75rem; font-weight: 600; white-space: nowrap; }
.role-admin { background: var(--c-primary); color: #fff; }
.role-developer { background: var(--c-ok-line); color: #fff; }
.role-ops { background: var(--c-info-line); color: #fff; }
.env-staging { background: var(--c-warn-bg); color: var(--c-warn); }
.env-production { background: var(--c-info-bg); color: var(--c-info); }
.env-onprem-test { background: #fff; color: var(--c-warn); border: 1px solid var(--c-warn-line); }
.env-onprem-production { background: #fff; color: var(--c-bad); border: 1px solid var(--c-bad-line); }
.act { background: #eef; color: #445; }
.status-success { background: var(--c-ok-bg); color: var(--c-ok); }
.status-failed { background: var(--c-bad-bg); color: var(--c-bad); }

/* ── Forms ───────────────────────────────────────────────────────────── */
label { display: block; margin: .75rem 0 .25rem; font-weight: 600; color: #444; }
select, input[type=text], input[type=password], input[type=number], input[type=url], input[type=email], textarea {
    width: 100%; padding: .65rem .75rem; border: 2px solid var(--c-line); border-radius: 6px; font-size: 1rem; background: #fff;
}
select:focus, input:focus, textarea:focus { outline: none; border-color: var(--c-primary); }
textarea { font-family: var(--mono); font-size: .85rem; }
button, .btn {
    display: inline-block; padding: .65rem 1.1rem; border: none; border-radius: 6px; font-size: .95rem; font-weight: 600;
    color: #fff; background: var(--grad-go); cursor: pointer; margin-top: .75rem; text-decoration: none; line-height: 1.2;
}
button:hover, .btn:hover { transform: translateY(-1px); }
button:disabled { background: #6c757d; cursor: not-allowed; transform: none; }
button.secondary, .btn.secondary { background: var(--grad); }
button.danger, .btn.danger { background: var(--grad-bad); }
button.link { background: none; color: var(--c-primary); padding: 0; margin: 0; font-weight: 600; }
button.link:hover { transform: none; text-decoration: underline; }
.btn-row { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }
.btn-row button, .btn-row .btn { margin-top: .5rem; }
.server-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: .5rem; margin: .5rem 0; }
.server-item { display: flex; align-items: center; gap: .5rem; padding: .5rem; background: #f8f9fa; border-radius: 6px; }
.server-item input { width: auto; margin: 0; }
.oc-steps { list-style: none; padding: 0; margin: .5rem 0 1rem; }
.oc-step { padding: .5rem .75rem; border-left: 3px solid #ddd; margin-bottom: .35rem; background: #f8f9fa; border-radius: 0 6px 6px 0; }
.oc-step.oc-running { border-color: var(--c-primary); }
.oc-step.oc-ok { border-color: var(--c-ok); }
.oc-step.oc-warn { border-color: var(--c-warn); }
.oc-step.oc-failed { border-color: var(--c-bad); background: var(--c-bad-bg); }
.oc-step.oc-skipped { opacity: .55; }
.permissions { font-size: .88rem; color: #555; padding: .75rem; background: #f8f9fa; border-radius: 6px; }
.cmd {
    display: block; background: #f4f5f9; border: 1px solid #e3e6f0; border-radius: 6px; padding: .5rem .65rem; margin-top: .4rem;
    font-family: var(--mono); font-size: .85em; overflow-x: auto; white-space: pre;
}
.dl { display: inline-block; padding: .3rem .7rem; border-radius: 6px; text-decoration: none; color: var(--c-primary); border: 2px solid var(--c-primary); font-weight: 600; font-size: .85em; white-space: nowrap; }
.dl:hover { background: var(--c-primary); color: #fff; }

/* A procedure reads as a procedure: numbered steps, each saying what it produces. */
.flow { border-left: 3px solid #e6e9f5; padding-left: .9rem; margin-top: 1.25rem; }
.flow-title { margin: 0; color: #444; font-size: 1rem; }
.flow-steps { margin: .5rem 0 0; padding-left: 1.3rem; }
.flow-steps > li { margin-bottom: 1rem; }
.flow-steps > li::marker { color: var(--c-primary); font-weight: 700; }
.flow-note { color: var(--c-muted); font-size: .9em; margin: .2rem 0 0; }

/* ── Log panels ──────────────────────────────────────────────────────── */
.log { background: var(--c-log); color: var(--c-log-text); padding: 1rem; border-radius: 6px; font-family: var(--mono); font-size: .82rem; white-space: pre-wrap; max-height: 60vh; overflow-y: auto; }
.log-content { display: none; margin-top: .5rem; max-height: 300px; }
.log-content.open { display: block; }
table.data tr.log-row { display: none; }
table.data tr.log-row.open { display: table-row; }
table.data tr.log-row .log { max-height: 300px; font-size: .78rem; }

/* ── Result drawer ───────────────────────────────────────────────────── */
.result { position: sticky; bottom: 0; z-index: 9; background: #fff; border-top: 1px solid var(--c-line); box-shadow: 0 -4px 16px rgba(0,0,0,.06); }
.result-bar { display: flex; align-items: center; gap: 1rem; padding: .45rem 1.5rem; font-size: .88rem; color: var(--c-muted); }
.result-title { flex: 1; }
.result.has-result .result-title { color: var(--c-text); font-weight: 600; }
.loading { display: none; color: var(--c-warn); font-weight: 600; }
#output {
    display: none; margin: 0 1.5rem .75rem; background: var(--c-log); color: var(--c-log-text); padding: 1rem; border-radius: 6px;
    font-family: var(--mono); font-size: .85rem; white-space: pre-wrap; max-height: 40vh; overflow-y: auto;
}
#output.success { background: var(--c-ok-bg); color: var(--c-ok); border-left: 4px solid var(--c-ok-line); }
#output.error { background: var(--c-bad-bg); color: var(--c-bad); border-left: 4px solid var(--c-bad-line); }
#download { display: none; margin: 0 1.5rem .75rem; }
#download a { display: inline-block; padding: .6rem 1rem; border-radius: 6px; text-decoration: none; color: #fff; font-weight: 600; background: var(--grad-go); }

/* ── Busy: the run owns the page until it finishes ───────────────────── */
/* Buttons are disabled in JS. Fields stay ENABLED so their values are still submitted
   (see setBusy in console.js); they are held off with pointer-events instead. A form
   marked data-busy="keep" is exempt — its read-only buttons must stay reachable. */
body.busy form[data-endpoint]:not([data-busy="keep"]) { pointer-events: none; opacity: .7; }
body.busy .sidebar nav a, body.busy .pill { pointer-events: none; opacity: .6; }

/* ── Login ───────────────────────────────────────────────────────────── */
body.login-page { display: flex; align-items: center; justify-content: center; min-height: 100vh; background: var(--grad); padding: 1rem; }
.login-box { background: #fff; padding: 2.5rem; border-radius: 12px; box-shadow: 0 10px 40px rgba(0,0,0,.3); width: 100%; max-width: 420px; }
.login-box .logo { text-align: center; margin-bottom: .5rem; }
.login-box h2 { text-align: center; margin: 0 0 .5rem; color: #333; }
.login-box .version { text-align: center; color: #888; font-size: .85rem; margin-bottom: 1.5rem; }
.login-box input { margin: .5rem 0; }
.login-box button { width: 100%; background: var(--grad); margin-top: 1rem; padding: .875rem; }
.login-box .ip-info { text-align: center; font-size: .8rem; color: #888; margin-top: 1rem; }

/* ── Narrow screens ──────────────────────────────────────────────────── */
@media (max-width: 900px) {
    .sidebar { transform: translateX(-100%); transition: transform .15s; width: min(85vw, 300px); }
    .nav-toggle:checked ~ .sidebar { transform: none; }
    .nav-toggle:checked ~ .nav-scrim { display: block; position: fixed; inset: 0; background: rgba(0,0,0,.3); z-index: 15; }
    .nav-open, .nav-close { display: inline-block; cursor: pointer; font-size: 1.3rem; padding: .2rem .5rem; }
    .page { margin-left: 0; }
    main { padding: 1rem; }
    .topbar { padding: .5rem 1rem; }
}

/* ── Records & docs ──────────────────────────────────────────────────── */
.inline-form { display: inline; margin: 0; }
.inline-form button { margin-top: 0; }
button.small, .btn.small { padding: .35rem .7rem; font-size: .8rem; white-space: nowrap; }
.inline-filter { display: flex; align-items: center; gap: .5rem; }
.inline-filter label.inline { display: inline; margin: 0; font-weight: 500; color: var(--c-muted); }
.inline-filter select { width: auto; padding: .4rem .6rem; font-size: .9rem; }
.doc-tabs { margin-bottom: 1rem; }
/* The guide is the one page that is a document, so it keeps a measure: a runbook set in
   one 2000px line is a runbook nobody finishes. Its tables and code blocks scroll inside
   it (see .prose table / .prose pre) rather than pushing this out. */
.prose { line-height: 1.6; padding: 2rem; max-width: 62rem; }
.prose h1 { margin-top: 0; border-bottom: 2px solid #eee; padding-bottom: .4rem; }
.prose h2 { margin-top: 2rem; border-bottom: 1px solid #eee; padding-bottom: .3rem; color: #333; font-size: 1.3rem; }
.prose h3 { margin-top: 1.5rem; color: #444; font-size: 1.05rem; }
.prose pre { background: var(--c-log); color: var(--c-log-text); padding: 1rem; border-radius: 8px; overflow-x: auto; }
.prose pre code { background: none; color: inherit; padding: 0; font-size: .85rem; }
.prose table { width: 100%; border-collapse: collapse; margin: 1rem 0; display: block; overflow-x: auto; }
.prose th, .prose td { padding: .6rem .75rem; text-align: left; border-bottom: 1px solid #eee; vertical-align: top; }
.prose th { background: #f8f9fa; font-weight: 600; }
.prose blockquote { margin: 1rem 0; padding: .75rem 1rem; background: #fff8e1; border-left: 4px solid var(--c-warn-line); border-radius: 0 6px 6px 0; }
.prose hr { border: none; border-top: 1px solid #e5e7eb; margin: 2rem 0; }
.prose ul, .prose ol { padding-left: 1.5rem; }
.prose li { margin: .25rem 0; }

/* ── Danger card (hotfix) ────────────────────────────────────────────── */
.card-danger { border: 2px solid var(--c-bad-bg); }
table.data.small td { padding: .35rem .5rem; }

/* ── Wizard ──────────────────────────────────────────────────────────── */
.wiz label { font-size: .9rem; margin: .6rem 0 .15rem; }
.wiz label.check { display: flex; align-items: center; gap: .5rem; font-weight: 500; }
.wiz label.check input { width: auto; }
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1rem; }
.grid3 { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 0 1rem; }
pre.key { background: #f0f2f5; padding: .75rem; border-radius: 6px; white-space: pre-wrap; word-break: break-all; font-size: .8rem; font-family: var(--mono); }
table.dbtable { width: 100%; border-collapse: collapse; margin: .25rem 0 .5rem; }
table.dbtable th { text-align: left; font-size: .8rem; color: var(--c-muted); font-weight: 600; padding: .2rem .4rem; }
table.dbtable td { padding: .2rem .4rem; vertical-align: middle; }
table.dbtable td:first-child { font-weight: 600; color: #444; font-size: .9rem; }
#checks { margin-top: 1rem; }
.chk { padding: .35rem .5rem; border-bottom: 1px solid #f0f0f0; font-size: .9rem; }
.chk .d { color: var(--c-muted); font-size: .82rem; margin-left: 1.55rem; word-break: break-all; }
.chk.ok  { color: var(--c-ok); }
.chk.bad { color: var(--c-bad); background: #fdf2f3; }
.stepnote { background: #eef2ff; border-radius: 6px; padding: .75rem 1rem; margin-top: 1rem; }
#fingerprintBox { display: none; }
#resultMsg { margin-top: 1rem; font-weight: 600; }
.drafts { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; background: #f7f8fa; border: 1px solid #e6e8eb; border-radius: 6px; padding: .5rem .6rem; margin: .75rem 0 .5rem; }
.drafts select { width: auto; min-width: 12rem; margin: 0; padding: .4rem .6rem; font-size: .9rem; }
.drafts button { margin: 0; }
.drafts .sep { flex: 1 1 auto; }
.draftnote { flex-basis: 100%; font-size: .82rem; }
@media (max-width: 700px) { .grid2, .grid3 { grid-template-columns: 1fr; } }

/* ── Workspace config editor ─────────────────────────────────────────── */
/* A form of settings rather than one action, so each control carries the sentence
   that says what it does — the old way of learning that was to change it and see. */
.field-note { font-size: .8rem; color: var(--c-muted); margin: .15rem 0 .9rem; }
.config-form h3 { margin-top: 1.5rem; }
.config-form input[type="file"] { font-size: .85rem; margin-bottom: .9rem; }
.colour-row { display: flex; align-items: center; gap: .5rem; }
.colour-row input[type="text"] { margin: 0; font-family: var(--mono); }
.colour-swatch { width: 2.4rem; min-width: 2.4rem; height: 2.4rem; padding: 2px; margin: 0; border: 1px solid #d7dade; border-radius: 6px; background: #fff; cursor: pointer; }
.colour-chip { display: inline-flex; align-items: center; gap: .3rem; margin-right: .4rem; }
.colour-chip i { width: .8rem; height: .8rem; border-radius: 3px; border: 1px solid rgba(0,0,0,.15); display: inline-block; }
.colour-chip code { font-size: .72rem; }
.logo-preview { background: repeating-conic-gradient(#f4f5f7 0% 25%, #fff 0% 50%) 50% / 12px 12px; border: 1px solid #e6e8eb; border-radius: 6px; padding: .4rem; margin-bottom: .4rem; display: inline-block; }
/* A row this tool disagrees with itself about. Flagged, never corrected: which side
   is right is a judgement call. */
tr.row-warn > td { background: var(--c-warn-bg); }
.button-link { display: inline-block; padding: .3rem .7rem; border-radius: 6px; background: #f0f2f5; color: #333; font-size: .85rem; text-decoration: none; white-space: nowrap; }
.button-link:hover { background: #e4e7eb; }
pre.diff { background: #f7f8fa; border: 1px solid #e6e8eb; border-radius: 6px; padding: .75rem; font-family: var(--mono); font-size: .8rem; overflow-x: auto; white-space: pre; }
