/* Ndwela OS design system — CSS custom properties for light/dark, kept to
   one file per DECISIONS.md #1 ("no JS framework, no build step"). Light
   values live on bare :root; dark values are layered on in two places —
   a prefers-color-scheme block (system default) and a [data-theme="dark"]
   block (explicit toggle, see workspace.js) — so both the OS setting and
   the in-app toggle work, and the toggle always wins over the system
   setting once the user has picked one. */

:root {
  --bg: #f7f7f5;
  --bg-raised: #ffffff;
  --panel: #ffffff;
  --border: #e0ddd6;
  --text: #2b2822;
  --muted: #6b6559;
  --accent: #8a5a3c;
  --accent-contrast: #ffffff;
  --good: #3f7a4f;
  --good-bg: #e9f3ec;
  --bad: #a3402f;
  --bad-bg: #fdecea;
  /* Was #b58900, which failed WCAG AA everywhere it was used: 2.98:1 as
     .warning-box text on --warn-bg, and 3.21:1 behind the white text of
     a .stage-badge.warn. Both need 4.5:1. Darkened to the nearest amber
     that clears it — 4.94:1 on --warn-bg, 5.33:1 on a panel, and 5.33:1
     for white text sitting on it. The dark theme's --warn already
     passed (7.46:1) and is unchanged. */
  --warn: #8a6500;
  --warn-bg: #fdf6e3;
  --focus-ring: #2f6fed;
  --shadow: 0 1px 2px rgba(30, 25, 15, 0.06), 0 1px 12px rgba(30, 25, 15, 0.04);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #171613;
    --bg-raised: #1f1d19;
    --panel: #1f1d19;
    --border: #34312a;
    --text: #ece8e0;
    --muted: #a39c8d;
    --accent: #d99a6c;
    --accent-contrast: #201408;
    --good: #7fce93;
    --good-bg: #1c2c20;
    --bad: #ef7f6a;
    --bad-bg: #33201c;
    --warn: #e0b74a;
    --warn-bg: #332a12;
    --focus-ring: #6fa2ff;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 1px 12px rgba(0, 0, 0, 0.24);
  }
}

:root[data-theme="dark"] {
  --bg: #171613;
  --bg-raised: #1f1d19;
  --panel: #1f1d19;
  --border: #34312a;
  --text: #ece8e0;
  --muted: #a39c8d;
  --accent: #d99a6c;
  --accent-contrast: #201408;
  --good: #7fce93;
  --good-bg: #1c2c20;
  --bad: #ef7f6a;
  --bad-bg: #33201c;
  --warn: #e0b74a;
  --warn-bg: #332a12;
  --focus-ring: #6fa2ff;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 1px 12px rgba(0, 0, 0, 0.24);
}

* { box-sizing: border-box; }

html { color-scheme: light dark; }
:root[data-theme="light"] html, :root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] html, :root[data-theme="dark"] { color-scheme: dark; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.5;
  transition: background-color 0.15s ease, color 0.15s ease;
}

a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: 3px;
}

/* Content that must reach assistive technology but not the screen. The
   1px-clip technique rather than display:none or visibility:hidden --
   both of those remove the element from the accessibility tree too,
   which defeats the purpose. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Off-screen until focused, then it lands over the header as a normal
   button. `top` animates rather than `display` toggling so the link is
   always focusable and always in the tab order. */
.skip-link {
  position: absolute;
  left: 1rem;
  top: -3rem;
  z-index: 200;
  background: var(--accent);
  color: var(--accent-contrast);
  padding: 0.55rem 1rem;
  border-radius: 0 0 6px 6px;
  text-decoration: none;
  font-weight: 600;
  font-size: 0.9rem;
  transition: top 0.12s ease;
}
.skip-link:focus { top: 0; }

/* `main` takes focus programmatically when the skip link is used, so the
   next Tab continues from the content -- but it is not a control and
   must not paint a focus ring. */
main:focus { outline: none; }

header {
  background: var(--bg-raised);
  border-bottom: 1px solid var(--border);
  padding: 0.6rem 1.5rem;
  position: sticky;
  top: 0;
  z-index: 10;
}

header nav {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  flex-wrap: wrap;
  max-width: 1300px;
  margin: 0 auto;
}

header a {
  color: var(--muted);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.9rem;
  padding: 0.3rem 0.1rem;
}

header a.brand {
  color: var(--text);
  font-size: 1.05rem;
  margin-right: 0.5rem;
  white-space: nowrap;
}

header a.active { color: var(--accent); }
header a:hover { color: var(--accent); }

.nav-search {
  margin-left: auto;
  display: flex;
  gap: 0.4rem;
  align-items: center;
}

.nav-search input {
  padding: 0.35rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  min-width: 200px;
  background: var(--panel);
  color: var(--text);
}

.theme-toggle {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: 6px;
  padding: 0.3rem 0.55rem;
  cursor: pointer;
  font-size: 0.95rem;
  line-height: 1;
}
.theme-toggle:hover { color: var(--accent); border-color: var(--accent); }

main {
  max-width: 1300px;
  margin: 0 auto;
  padding: 1.5rem;
}

.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 0.75rem;
  margin-bottom: 1.5rem;
}

.tile {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1rem;
  text-decoration: none;
  color: var(--text);
  display: block;
  box-shadow: var(--shadow);
  transition: transform 0.1s ease, border-color 0.1s ease;
}
.tile:hover { border-color: var(--accent); transform: translateY(-1px); }

.tile .tile-value { font-size: 2rem; font-weight: 700; line-height: 1; }
.tile .tile-label { color: var(--muted); font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.02em; margin-top: 0.35rem; }
.tile.tile-good .tile-value { color: var(--good); }
.tile.tile-bad .tile-value { color: var(--bad); }

.bar-chart { display: flex; flex-direction: column; gap: 0.6rem; }
.bar-chart-row { display: grid; grid-template-columns: 8rem 1fr 2.5rem; align-items: center; gap: 0.6rem; font-size: 0.85rem; }
.bar-chart-label { color: var(--muted); text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bar-chart-track { background: var(--bg); border: 1px solid var(--border); border-radius: 6px; height: 0.9rem; overflow: hidden; }
.bar-chart-fill { background: var(--accent); height: 100%; border-radius: 6px 0 0 6px; transition: width 0.4s ease; }
.bar-chart-value { text-align: right; font-variant-numeric: tabular-nums; }

.section-heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 0.5rem;
}

.queue-list { list-style: none; margin: 0; padding: 0; }
.queue-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--border);
  gap: 0.75rem;
}
.queue-item:last-child { border-bottom: none; }
.queue-reason { color: var(--muted); font-size: 0.85rem; }

.pipeline-columns, .board-columns-wide {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.75rem;
  align-items: start;
  overflow-x: auto;
}
.pipeline-column {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.75rem;
  min-height: 100px;
}
.pipeline-column h2, .pipeline-column h3 { font-size: 0.8rem; text-transform: uppercase; color: var(--muted); margin: 0 0 0.5rem; letter-spacing: 0.02em; }
.pipeline-card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.5rem;
  margin-bottom: 0.5rem;
  font-size: 0.9rem;
}
.pipeline-card .card-actions { margin-top: 0.35rem; display: flex; gap: 0.35rem; flex-wrap: wrap; }
.pipeline-card[draggable="true"] { cursor: grab; }
.pipeline-card[draggable="true"]:active { cursor: grabbing; }
.pipeline-column[data-drop-target="true"] { transition: background-color 0.1s ease, border-color 0.1s ease; }
.pipeline-column.drop-target-active { background: var(--good-bg); border-color: var(--good); }

.search-results-group { margin-bottom: 1.5rem; }
.search-result-row { padding: 0.4rem 0; border-bottom: 1px solid var(--border); }
.entity-tag {
  display: inline-block;
  font-size: 0.72rem;
  text-transform: uppercase;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.05rem 0.5rem;
  margin-left: 0.4rem;
}

.metrics-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.75rem;
}

h1, h2, h3 { margin-top: 0; }

.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.25rem;
  margin-bottom: 1.25rem;
  box-shadow: var(--shadow);
}

/* Long unbreakable runs in prose must not scroll the whole page
   sideways. The Changelog was 927px wide at a 390px viewport because of
   strings like `Contact`/`Client`/`Opportunity`/`Proposal`/... — a
   ~100-character token with no space in it, and browsers do not break
   on "/". `anywhere` (rather than `break-word`) also lets the run
   shrink the container's min-content width, which is what stops it
   pushing the page out.

   Scoped to prose, never to tables: a data table's cells stay nowrap and
   scroll inside their own .table-scroll wrapper instead. */
.panel p, .panel li, .timeline-entry p, .changelog-subject, .changelog-body, .hub-card p {
  overflow-wrap: anywhere;
}

/* `min-width: 0` matters as much as the overflow itself: as a flex or
   grid item, this box's automatic minimum size is its content's
   min-content width, so a wide table would push its whole track wider
   than the viewport instead of scrolling inside this wrapper. */
.table-scroll { overflow-x: auto; min-width: 0; }
table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: 0.5rem 0.4rem; border-bottom: 1px solid var(--border); white-space: nowrap; }
th { color: var(--muted); font-weight: 600; font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.01em; }
td.wrap { white-space: normal; }

/* Free-text cells (`category`, `location`) come from directory sources
   and are occasionally enormous — one 137-character category value made
   the Lead Queue's Sector column 1079px wide, pushing lead score,
   outreach stage and every remaining column off screen for all 25 rows.
   Letting them wrap instead is no better: a 79-character address turns
   every row into three lines.

   So: clip to a readable width with an ellipsis, and carry the full
   value in `title` for hover. Nothing is lost to assistive technology —
   the complete text is still the cell's content, only visually
   truncated. */
td.truncate {
  max-width: 18rem;
  overflow: hidden;
  text-overflow: ellipsis;
}
td.truncate-wide { max-width: 26rem; }

/* Key-value settings tables (a label column + a wide input column) —
   unlike a data table, forcing the label to one line is what pushes
   these wide at narrow viewports (no table-scroll wrapper helps a form
   the user needs to type into anyway); wrapping the label and letting
   the input column take the remaining width keeps the whole page from
   scrolling horizontally instead. */
table.kv-table th, table.kv-table td { white-space: normal; overflow-wrap: anywhere; }
table.kv-table th { width: 35%; }
table.kv-table input, table.kv-table textarea, table.kv-table select { max-width: 100%; }
/* Text inputs fill their column; checkboxes must keep their intrinsic size. */
table.kv-table input:not([type="checkbox"]):not([type="radio"]),
table.kv-table textarea { width: 100%; }
/* ...except fields whose content is inherently short. A 620px-wide box
   for a two-digit page size tells the user to expect an essay. */
table.kv-table input[type="number"] { max-width: 8rem; }
table.kv-table input.short { max-width: 12rem; }

a.org-link { color: var(--accent); font-weight: 600; text-decoration: none; }
a.org-link:hover { text-decoration: underline; }

.stage-badge {
  display: inline-block;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-contrast);
  font-size: 0.82rem;
  font-weight: 600;
  white-space: nowrap;
}
.stage-badge.good { background: var(--good); color: var(--bg-raised); }
.stage-badge.bad { background: var(--bad); color: var(--bg-raised); }
.stage-badge.warn { background: var(--warn); color: var(--bg-raised); }
.stage-badge.muted-badge { background: var(--border); color: var(--muted); }

.stage-form-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.75rem;
}

.stage-form-row form { margin: 0; }

button, .button {
  background: var(--accent);
  color: var(--accent-contrast);
  border: none;
  border-radius: 6px;
  padding: 0.5rem 0.9rem;
  font-size: 0.9rem;
  cursor: pointer;
  font-family: inherit;
}

button.secondary, .button.secondary { background: var(--muted); }
button.small, .button.small { padding: 0.3rem 0.6rem; font-size: 0.82rem; }
button:hover, .button:hover { opacity: 0.9; }

.message-box {
  white-space: pre-wrap;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.75rem;
  font-family: ui-monospace, monospace;
  font-size: 0.85rem;
}

.muted { color: var(--muted); }

/* Opportunity Profile: "in its favour" beside "in the way". Two columns
   on a wide screen, stacked on a narrow one -- auto-fit rather than a
   media query so it collapses at whatever width the panel actually gets,
   not at a guessed breakpoint. */
.reason-columns {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1.25rem;
  margin-top: 0.5rem;
}
.reason-columns h3 { font-size: 0.8rem; text-transform: uppercase; color: var(--muted); letter-spacing: 0.02em; margin-bottom: 0.4rem; }
.reason-list { margin: 0; padding-left: 1.1rem; font-size: 0.9rem; }
.reason-list li { margin-bottom: 0.3rem; overflow-wrap: anywhere; }
.reason-list li::marker { color: var(--good); }
.reason-list-blocked li::marker { color: var(--bad); }
.reason-footnote { font-size: 0.8rem; margin-bottom: 0; }

.error-box {
  background: var(--bad-bg);
  border: 1px solid var(--bad);
  color: var(--bad);
  border-radius: 6px;
  padding: 1rem;
}

.warning-box {
  background: var(--warn-bg);
  border: 1px solid var(--warn);
  color: var(--warn);
  border-radius: 6px;
  padding: 0.6rem 0.9rem;
  font-size: 0.9rem;
  margin: 0.5rem 0;
}

.followup-form {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-wrap: wrap;
  margin-top: 0.5rem;
}

.filter-form {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}

.followup-form input[type="text"], .followup-form input[type="datetime-local"], .followup-form select,
.filter-form input, .filter-form select {
  padding: 0.4rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--panel);
  color: var(--text);
}

/* Without a floor, flexbox shrinks the narrower filter controls until
   their own placeholder is clipped ("Min lea…"). Each still shrinks —
   just not below the width of the label it is showing. */
.filter-form input, .filter-form select { min-width: 9rem; }
.filter-form input[type="number"] { min-width: 8rem; }

.hidden { display: none; }

summary { cursor: pointer; font-weight: 600; }
summary .stage-badge { font-weight: 600; }
details.panel > *:not(summary) { margin-top: 0.75rem; }


.assistant-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0.9rem;
  margin-bottom: 1.25rem;
}
.assistant-grid h3 { font-size: 0.95rem; margin-bottom: 0.4rem; }
.assistant-grid > div > .queue-item:last-child { border-bottom: none; }

.hub-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0.9rem;
}
.hub-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.1rem;
  text-decoration: none;
  color: var(--text);
  box-shadow: var(--shadow);
}
.hub-card h2, .hub-card h3 { margin-bottom: 0.35rem; font-size: 1.05rem; }
.hub-card p { margin: 0; color: var(--muted); font-size: 0.88rem; }
.hub-card:hover { border-color: var(--accent); }

.calendar-day {
  display: flex;
  gap: 1rem;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--border);
}
.calendar-day:last-child { border-bottom: none; }
.calendar-date {
  min-width: 110px;
  font-weight: 700;
  color: var(--muted);
}
.calendar-entries { flex: 1; display: flex; flex-direction: column; gap: 0.4rem; }
.calendar-entry { display: flex; justify-content: space-between; gap: 0.75rem; align-items: baseline; }

.bar-row { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.5rem; }
.bar-label { width: 140px; font-size: 0.85rem; flex-shrink: 0; }
.bar-track { flex: 1; background: var(--bg); border-radius: 4px; height: 10px; overflow: hidden; border: 1px solid var(--border); }
.bar-fill { background: var(--accent); height: 100%; }
.bar-value { width: 50px; text-align: right; font-size: 0.85rem; color: var(--muted); }

.pagination { display: flex; gap: 0.6rem; margin-top: 1rem; }

kbd {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.05rem 0.4rem;
  font-family: ui-monospace, monospace;
  font-size: 0.82rem;
}

.shortcut-help {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}
/* Higher specificity than the bare `.shortcut-help` rule above (two
   classes beats one) so `hidden` always wins regardless of source
   order — a `.hidden` element must never be visible. */
.shortcut-help.hidden { display: none; }
.shortcut-help .panel { max-width: 420px; width: 90%; }
.shortcut-help table td, .shortcut-help table th { border: none; padding: 0.25rem 0.4rem; }

/* ---- Platform pages: Project Status, Metrics, Changelog, Architecture ---- */

.status-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 1rem;
}
.status-card-header { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.status-card-header h2, .status-card-header h3 { margin: 0; font-size: 1.05rem; }
.status-layer { margin: 0.2rem 0 0.6rem; font-size: 0.8rem; }
.status-limitations { margin-top: 0.75rem; font-size: 0.85rem; color: var(--muted); }

.timeline { display: flex; flex-direction: column; gap: 1rem; }
.timeline-entry {
  background: var(--panel);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
  padding: 0.9rem 1.1rem;
  box-shadow: var(--shadow);
}
.timeline-entry h3 { margin: 0 0 0.35rem; }
.timeline-entry p { margin: 0; color: var(--muted); font-size: 0.9rem; }

.changelog-date { margin: 1.25rem 0 0.5rem; color: var(--muted); font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.03em; }
.changelog-list { list-style: none; padding: 0; margin: 0; }
.changelog-entry { padding: 0.5rem 0; border-bottom: 1px solid var(--border); }
.changelog-entry:last-child { border-bottom: none; }
.changelog-subject { font-size: 0.92rem; }
.changelog-body { margin-top: 0.25rem; color: var(--muted); font-size: 0.82rem; white-space: pre-wrap; }

.diagram-chain { display: flex; flex-direction: column; align-items: center; gap: 0.15rem; margin-bottom: 1rem; }
.diagram-node {
  width: 100%;
  max-width: 420px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.6rem 1rem;
  font: inherit;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  box-shadow: var(--shadow);
  transition: border-color 0.1s ease, background 0.1s ease;
}
.diagram-node:hover { border-color: var(--accent); }
.diagram-node.active { border-color: var(--accent); background: var(--accent); color: var(--accent-contrast); }
.diagram-arrow { color: var(--muted); line-height: 1; font-size: 1.1rem; }
.diagram-detail { margin-bottom: 1.5rem; }
.diagram-detail-panel h3 { margin-bottom: 0.35rem; }
.diagram-detail-panel p { margin: 0; color: var(--muted); }
.diagram-detail-panel.hidden { display: none; }

/* minmax(0, 1fr), not 1fr: a grid track's automatic minimum is its
   content's min-content width, so one wide table in a documentation
   page stretched this track to 1027px inside a 390px viewport and
   scrolled the entire page sideways. minmax(0, ...) lets the track
   shrink and the table scroll inside its own wrapper instead. */
.docs-layout { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 1.5rem; align-items: start; }
.docs-nav { display: flex; flex-direction: column; gap: 0.3rem; position: sticky; top: 1rem; }
.docs-nav a { padding: 0.4rem 0.6rem; border-radius: 6px; color: var(--text); text-decoration: none; font-size: 0.9rem; }
.docs-nav a:hover { background: var(--panel); }
.docs-nav a.active { background: var(--accent); color: var(--accent-contrast); }
.docs-nav-back { color: var(--muted) !important; font-size: 0.85rem !important; margin-bottom: 0.4rem; }
.docs-content h1 { margin-top: 0; }
.docs-content h2 { margin-top: 1.5rem; }
.docs-content h3 { margin-top: 1.1rem; }
.docs-content p { line-height: 1.6; }
.docs-content pre { background: var(--bg); border: 1px solid var(--border); border-radius: 8px; padding: 0.9rem; overflow-x: auto; }
.docs-content code { font-family: ui-monospace, monospace; font-size: 0.85em; }
.docs-content ul, .docs-content ol { padding-left: 1.4rem; line-height: 1.6; }
.docs-content table { margin: 0.75rem 0; }

@media (max-width: 720px) {
  .docs-layout { grid-template-columns: minmax(0, 1fr); }
  .docs-nav { position: static; flex-direction: row; flex-wrap: wrap; }
}

.tour-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 110;
}
.tour-overlay.hidden { display: none; }
.tour-panel { max-width: 440px; width: 90%; animation: tour-pop 0.15s ease; }
.tour-step-count { color: var(--muted); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.03em; margin-bottom: 0.3rem; }
.tour-controls { display: flex; align-items: center; justify-content: space-between; margin-top: 1.25rem; }
@keyframes tour-pop { from { opacity: 0; transform: scale(0.97); } to { opacity: 1; transform: scale(1); } }

.status-page { text-align: center; max-width: 480px; margin: 3rem auto; }
.status-page-code { font-size: 4rem; font-weight: 700; color: var(--accent); line-height: 1; margin-bottom: 0.5rem; }
.status-page-code-bad { color: var(--bad); }
.status-page .stage-form-row { justify-content: center; margin-top: 1.25rem; }

/* The region is rendered on every page whether or not there is anything
   in it, so that it already exists in the accessibility tree when a
   message arrives (a live region created at the same moment as its
   content is often not announced). base.html strips the whitespace
   inside it so that "no messages" is genuinely :empty and this rule can
   collapse the gap it would otherwise leave at the top of every page. */
.flash-messages { margin-bottom: 1rem; display: flex; flex-direction: column; gap: 0.5rem; }
.flash-messages:empty { display: none; }
.flash-message {
  padding: 0.65rem 1rem;
  border-radius: 8px;
  font-size: 0.9rem;
  animation: flash-in 0.2s ease;
}
.flash-success { background: color-mix(in srgb, var(--good) 15%, var(--panel)); border: 1px solid var(--good); color: var(--good); }
.flash-error { background: color-mix(in srgb, var(--bad) 15%, var(--panel)); border: 1px solid var(--bad); color: var(--bad); }
@keyframes flash-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }

main { animation: page-fade-in 0.15s ease; }
@keyframes page-fade-in { from { opacity: 0; } to { opacity: 1; } }

/* Honour the OS-level "reduce motion" setting (WCAG 2.3.3). Everything
   here is decorative -- a page fade, a flash slide-in, the tour's pop,
   bar-chart fills growing, tiles lifting on hover -- so it can all be
   reduced to effectively instant without losing any information. Motion
   is not removed entirely (0.01ms rather than `none`) so that
   animation/transition end events still fire for anything that might
   depend on them. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .tile:hover { transform: none; }
}

/* Search-result snippets: FTS marks the matched terms, and
   workspace.core.formatting.highlight_snippet turns those markers into
   <mark>. Browsers default <mark> to a yellow that ignores the theme. */
.search-snippet mark {
  background: color-mix(in srgb, var(--accent) 22%, transparent);
  color: inherit;
  border-radius: 3px;
  padding: 0 0.15rem;
  font-weight: 600;
}

/* The threshold behind each Daily Assistant column, so its count can be
   reconciled with the headline tiles instead of appearing to contradict
   them. */
.assistant-hint { font-size: 0.78rem; margin: -0.2rem 0 0.5rem; }

/* Confirm-dialog accept button. The action behind it is irreversible, so
   it must not look like the ordinary accent-coloured "save" button the
   user clicks all day. */
button.danger, .button.danger { background: var(--bad); color: var(--bg-raised); }
#confirm-dialog .panel { max-width: 30rem; width: 90%; }
#confirm-dialog p { margin: 0.25rem 0 0; }

/* The signed-in user menu in the nav — replaced the old "acting as"
   selector once migration 0012 made this a real login
   (`canonical/DECISIONS.md` #33). Styled as what it is now: a name and
   a sign-out control, not a picker. */
.nav-user { display: flex; align-items: center; gap: 0.5rem; font-size: 0.85rem; }
.nav-user .nav-user-role { color: var(--muted); }
.nav-user form { margin: 0; }

/* Mission Control's ownership blocks and the stage badges reuse the
   existing badge/panel vocabulary; only the account-pipeline board needs
   room for eleven columns rather than nine, so its cards stay compact. */
.pipeline-card .queue-reason { font-size: 0.75rem; }

/* Login, invitation-acceptance, and password-reset pages — the only
   pages an unauthenticated request can ever reach
   (`canonical/DECISIONS.md` #33). Deliberately not the app shell
   (`base.html`): showing the full nav to someone who isn't signed in
   yet would expose page names and invite clicking into a redirect loop
   back to this same form. */
.auth-body { display: flex; min-height: 100vh; align-items: center; justify-content: center; }
.auth-main { width: 100%; max-width: 26rem; padding: 1.5rem; }
.auth-panel { display: flex; flex-direction: column; gap: 1rem; }
.auth-panel .brand { font-weight: 700; font-size: 1.1rem; text-decoration: none; }
.auth-panel form { display: flex; flex-direction: column; gap: 0.85rem; }
.auth-panel label { font-size: 0.85rem; font-weight: 600; }
.auth-panel input[type="email"], .auth-panel input[type="password"], .auth-panel input[type="text"] {
  width: 100%;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-raised);
  color: var(--text);
  font-size: 0.95rem;
}
.auth-panel .field { display: flex; flex-direction: column; gap: 0.3rem; }
.auth-panel .remember-me { flex-direction: row; align-items: center; gap: 0.4rem; }
.auth-panel .remember-me label { font-weight: 400; }
.auth-panel .auth-links { display: flex; justify-content: space-between; font-size: 0.85rem; }
.auth-panel .auth-hint { font-size: 0.82rem; color: var(--muted); }
